ia32_map_regs.c 6.62 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
3
4
/**
 * Register mapping for firm nodes. Stolen from bearch_firm :)
 * $Id$
 */
5
6
7
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
Christian Würdig's avatar
Christian Würdig committed
8
9
10
11
12

#include <stdlib.h>

#include "ia32_map_regs.h"
#include "ia32_new_nodes.h"
Christian Würdig's avatar
Christian Würdig committed
13
14
15
16
17
18
19
#include "gen_ia32_regalloc_if.h"

static int maxnum_gpreg_args = 3;   /* maximum number of int arguments passed in registers; default 3 */
static int maxnum_fpreg_args = 5;   /* maximum number of float arguments passed in registers; default 5 */

/* this is the order of the assigned registers usesd for parameter passing */

20
21
22
23
24
25
26
const arch_register_t *gpreg_param_reg_std[] = {
	&ia32_gp_regs[REG_EAX],
	&ia32_gp_regs[REG_EDX],
	&ia32_gp_regs[REG_ECX],
	&ia32_gp_regs[REG_EBX],
	&ia32_gp_regs[REG_EDI],
	&ia32_gp_regs[REG_ESI]
Christian Würdig's avatar
Christian Würdig committed
27
28
};

29
30
31
32
33
34
35
const arch_register_t *gpreg_param_reg_this[] = {
	&ia32_gp_regs[REG_ECX],
	&ia32_gp_regs[REG_EAX],
	&ia32_gp_regs[REG_EDX],
	&ia32_gp_regs[REG_EBX],
	&ia32_gp_regs[REG_EDI],
	&ia32_gp_regs[REG_ESI]
Christian Würdig's avatar
Christian Würdig committed
36
37
};

38
39
40
41
42
43
44
45
46
const arch_register_t *fpreg_param_reg_std[] = {
	&ia32_fp_regs[REG_XMM0],
	&ia32_fp_regs[REG_XMM1],
	&ia32_fp_regs[REG_XMM2],
	&ia32_fp_regs[REG_XMM3],
	&ia32_fp_regs[REG_XMM4],
	&ia32_fp_regs[REG_XMM5],
	&ia32_fp_regs[REG_XMM6],
	&ia32_fp_regs[REG_XMM7]
Christian Würdig's avatar
Christian Würdig committed
47
48
};

49
const arch_register_t *fpreg_param_reg_this[] = {
Christian Würdig's avatar
Christian Würdig committed
50
	NULL,  /* in case of a "this" pointer, the first parameter must not be a float */
51
52
53
54
55
56
57
58
	&ia32_fp_regs[REG_XMM0],
	&ia32_fp_regs[REG_XMM1],
	&ia32_fp_regs[REG_XMM2],
	&ia32_fp_regs[REG_XMM3],
	&ia32_fp_regs[REG_XMM4],
	&ia32_fp_regs[REG_XMM5],
	&ia32_fp_regs[REG_XMM6],
	&ia32_fp_regs[REG_XMM7]
Christian Würdig's avatar
Christian Würdig committed
59
60
};

Christian Würdig's avatar
Christian Würdig committed
61

62
63
64
65

/* Mapping to store registers in firm nodes */

struct ia32_irn_reg_assoc {
Christian Würdig's avatar
Christian Würdig committed
66
67
68
69
	const ir_node *irn;
	const arch_register_t *reg;
};

70
71
72
int ia32_cmp_irn_reg_assoc(const void *a, const void *b, size_t len) {
	const struct ia32_irn_reg_assoc *x = a;
	const struct ia32_irn_reg_assoc *y = b;
Christian Würdig's avatar
Christian Würdig committed
73

74
	return x->irn != y->irn;
Christian Würdig's avatar
Christian Würdig committed
75
76
}

77
78
static struct ia32_irn_reg_assoc *get_irn_reg_assoc(const ir_node *irn, set *reg_set) {
	struct ia32_irn_reg_assoc templ;
Christian Würdig's avatar
Christian Würdig committed
79
80
81
82
83
84
85
86
87
	unsigned int hash;

	templ.irn = irn;
	templ.reg = NULL;
	hash = HASH_PTR(irn);

	return set_insert(reg_set, &templ, sizeof(templ), hash);
}

88
89
void ia32_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set) {
	struct ia32_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
Christian Würdig's avatar
Christian Würdig committed
90
91
92
	assoc->reg = reg;
}

93
94
const arch_register_t *ia32_get_firm_reg(const ir_node *irn, set *reg_set) {
	struct ia32_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
Christian Würdig's avatar
Christian Würdig committed
95
96
97
98
	return assoc->reg;
}


99

Christian Würdig's avatar
Christian Würdig committed
100
101
102
103
104
/**
 * Check all parameters and determine the maximum number of parameters
 * to pass in gp regs resp. in fp regs.
 *
 * @param n       The number of parameters
105
 * @param modes   The list of the parameter modes
Christian Würdig's avatar
Christian Würdig committed
106
107
108
109
 * @param n_int   Holds the number of int parameters to be passed in regs after the call
 * @param n_float Holds the number of float parameters to be passed in regs after the call
 * @return        The number of the last parameter to be passed in register
 */
110
int ia32_get_n_regparam_class(int n, ir_mode **modes, int *n_int, int *n_float) {
Christian Würdig's avatar
Christian Würdig committed
111
112
113
	int i, finished = 0;

	for (i = 0; i < n && !finished; i++) {
114
		if (mode_is_int(modes[i])) {
Christian Würdig's avatar
Christian Würdig committed
115
116
			*n_int = *n_int + 1;
		}
117
		else if (mode_is_float(modes[i])) {
Christian Würdig's avatar
Christian Würdig committed
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
			*n_float = *n_float + 1;
		}
		else {
			finished = 1;
		}

		/* test for maximum */
		if (*n_int == maxnum_gpreg_args || *n_float == maxnum_fpreg_args) {
			finished = 1;
		}
	}

	return i - 1;
}


/**
135
 * Returns the register for parameter nr.
Christian Würdig's avatar
Christian Würdig committed
136
137
 *
 * @param n     The number of parameters
138
 * @param modes The list of the parameter modes
Christian Würdig's avatar
Christian Würdig committed
139
140
 * @param nr    The number of the parameter to return the requirements for
 * @param cc    The calling convention
141
 * @return      The register
Christian Würdig's avatar
Christian Würdig committed
142
 */
Christian Würdig's avatar
Christian Würdig committed
143
const arch_register_t *ia32_get_RegParam_reg(int n, ir_mode **modes, long nr, unsigned cc) {
144
145
146
	const arch_register_t **current_gpreg_param_reg;
	const arch_register_t **current_fpreg_param_reg;
	const arch_register_t  *param_reg = NULL;
Christian Würdig's avatar
Christian Würdig committed
147
148
149
150
151
	int n_gpregparam = 0;
	int n_fpregparam = 0;
	int i, done      = 0;
	int cur_gp_idx   = 0;
	int cur_fp_idx   = 0;
152
	int biggest_n    = ia32_get_n_regparam_class(n, modes, &n_gpregparam, &n_fpregparam);
Christian Würdig's avatar
Christian Würdig committed
153
154
155

	/* Check if parameter #nr is in range for passing in register */
	if (nr <= biggest_n) {
156
157
		current_gpreg_param_reg = gpreg_param_reg_std;
		current_fpreg_param_reg = fpreg_param_reg_std;
Christian Würdig's avatar
Christian Würdig committed
158
159

		if (cc & cc_this_call) {
160
161
			current_gpreg_param_reg = gpreg_param_reg_this;
			current_fpreg_param_reg = fpreg_param_reg_this;
Christian Würdig's avatar
Christian Würdig committed
162
163
164
165
		}

		/* loop over all parameters and determine whether its a int or float register parameter */
		for (i = 0; i < nr && !done && (cc & cc_reg_param); i++) {
166
			if (mode_is_int(modes[i]) && cur_gp_idx < maxnum_gpreg_args) {
Christian Würdig's avatar
Christian Würdig committed
167
168
169
				/* param can be passed in general purpose register and we have some registers left */
				cur_gp_idx++;
			}
170
			else if (mode_is_float(modes[i]) && cur_fp_idx < maxnum_fpreg_args) {
Christian Würdig's avatar
Christian Würdig committed
171
				/* param can be passed in floating point register and we have some registers left */
172
				assert(current_gpreg_param_reg[cur_fp_idx] && "'this' pointer cannot be passed as float");
Christian Würdig's avatar
Christian Würdig committed
173
174
175
176
177
				cur_fp_idx++;
			}
		}

		/* now: i == nr, that's the parameter requirement we want */
178
		if (mode_is_int(modes[i]) && cur_gp_idx < maxnum_gpreg_args) {
Christian Würdig's avatar
Christian Würdig committed
179
			/* parameter #nr can be passed in general purpose register */
180
			param_reg = current_gpreg_param_reg[i];
Christian Würdig's avatar
Christian Würdig committed
181
		}
182
		else if (mode_is_float(modes[i]) && cur_fp_idx < maxnum_fpreg_args) {
Christian Würdig's avatar
Christian Würdig committed
183
			/* parameter #nr can be passed in floating point register */
184
			param_reg = current_fpreg_param_reg[i];
Christian Würdig's avatar
Christian Würdig committed
185
186
187
188
189
190
		}
		else {
			assert(0 && "This should not happen!");
		}
	}

191
	return param_reg;
Christian Würdig's avatar
Christian Würdig committed
192
193
194
195
}



Christian Würdig's avatar
Christian Würdig committed
196
197
198
199
/**
 * Translates the projnum into a "real" argument position for register
 * requirements dependend on the predecessor.
 */
200
long ia32_translate_proj_pos(const ir_node *proj) {
Christian Würdig's avatar
Christian Würdig committed
201
202
203
204
205
206
207
208
209
210
211
	ir_node *pred = get_Proj_pred(proj);
	long nr       = get_Proj_proj(proj);

	if (is_ia32_Load(pred)) {
		if (nr == pn_Load_res)
			return 0;
		assert(0 && "unsupported Proj(Load) number");
	}
	else if (is_ia32_Store(pred)) {
		return 0;
	}
212
	else if (is_ia32_CondJmp(pred)) {
Christian Würdig's avatar
Christian Würdig committed
213
214
215
216
217
		return 0;
	}
	else if (is_ia32_SwitchJmp(pred)) {
		return 0;
	}
218
	else if (is_ia32_Cdq(pred) || is_ia32_Mulh(pred)) {
Christian Würdig's avatar
Christian Würdig committed
219
220
221
222
223
224
225
226
227
228
229
		if (nr == pn_EAX)
			return 0;
		if (nr == pn_EDX)
			return 1;
	}
	else if (is_ia32_DivMod(pred)) {
		if (nr == pn_DivMod_res_div || pn_Div_res)
			return 0;
		if (nr == pn_DivMod_res_mod || pn_Mod_res)
			return 1;
	}
230
231
232
233
234
235
	else if (is_ia32_fDiv(pred)) {
		if (nr == pn_Quot_res)
			return 0;
		else
			assert(0 && "there should be no more Projs for a fDiv");
	}
Christian Würdig's avatar
Christian Würdig committed
236
237
238
239
240
241
242
	else if (is_ia32_Call(pred)) {
		return 0;
	}
	else if (get_irn_mode(proj) == mode_X && nr == pn_Start_X_initial_exec) {
		return 0;
	}
	else if (is_Proj(pred)) {
243
		return nr;
Christian Würdig's avatar
Christian Würdig committed
244
245
246
247
248
	}
	else if (get_irn_opcode(pred) == iro_Start) {
		return nr;
	}

Christian Würdig's avatar
Christian Würdig committed
249
250
//	assert(0 && "unsupported Proj(X)");
	return nr;
Christian Würdig's avatar
Christian Würdig committed
251
}