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 arch_register_t *gpreg_param_reg_std[] = {
21 &ia32_gp_regs[REG_EAX],
22 &ia32_gp_regs[REG_EDX],
23 &ia32_gp_regs[REG_ECX],
24 &ia32_gp_regs[REG_EBX],
25 &ia32_gp_regs[REG_EDI],
26 &ia32_gp_regs[REG_ESI]
29 const arch_register_t *gpreg_param_reg_this[] = {
30 &ia32_gp_regs[REG_ECX],
31 &ia32_gp_regs[REG_EAX],
32 &ia32_gp_regs[REG_EDX],
33 &ia32_gp_regs[REG_EBX],
34 &ia32_gp_regs[REG_EDI],
35 &ia32_gp_regs[REG_ESI]
38 const arch_register_t *fpreg_param_reg_std[] = {
39 &ia32_fp_regs[REG_XMM0],
40 &ia32_fp_regs[REG_XMM1],
41 &ia32_fp_regs[REG_XMM2],
42 &ia32_fp_regs[REG_XMM3],
43 &ia32_fp_regs[REG_XMM4],
44 &ia32_fp_regs[REG_XMM5],
45 &ia32_fp_regs[REG_XMM6],
46 &ia32_fp_regs[REG_XMM7]
49 const arch_register_t *fpreg_param_reg_this[] = {
50 NULL, /* in case of a "this" pointer, the first parameter must not be a float */
51 &ia32_fp_regs[REG_XMM0],
52 &ia32_fp_regs[REG_XMM1],
53 &ia32_fp_regs[REG_XMM2],
54 &ia32_fp_regs[REG_XMM3],
55 &ia32_fp_regs[REG_XMM4],
56 &ia32_fp_regs[REG_XMM5],
57 &ia32_fp_regs[REG_XMM6],
58 &ia32_fp_regs[REG_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 list of the parameter modes
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_mode **modes, int *n_int, int *n_float) {
150 for (i = 0; i < n && !finished; i++) {
151 if (mode_is_int(modes[i])) {
154 else if (mode_is_float(modes[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 for parameter nr.
174 * @param n The number of parameters
175 * @param modes The list of the parameter modes
176 * @param nr The number of the parameter to return the requirements for
177 * @param cc The calling convention
178 * @return The register
180 const arch_register_t *ia32_get_RegParam_reg(int n, ir_mode **modes, long nr, unsigned cc) {
181 const arch_register_t **current_gpreg_param_reg;
182 const arch_register_t **current_fpreg_param_reg;
183 const arch_register_t *param_reg = NULL;
184 int n_gpregparam = 0;
185 int n_fpregparam = 0;
189 int biggest_n = ia32_get_n_regparam_class(n, modes, &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_reg = gpreg_param_reg_std;
194 current_fpreg_param_reg = fpreg_param_reg_std;
196 if (cc & cc_this_call) {
197 current_gpreg_param_reg = gpreg_param_reg_this;
198 current_fpreg_param_reg = fpreg_param_reg_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(modes[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(modes[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_reg[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(modes[i]) && cur_gp_idx < maxnum_gpreg_args) {
216 /* parameter #nr can be passed in general purpose register */
217 param_reg = current_gpreg_param_reg[i];
219 else if (mode_is_float(modes[i]) && cur_fp_idx < maxnum_fpreg_args) {
220 /* parameter #nr can be passed in floating point register */
221 param_reg = current_fpreg_param_reg[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)) {
253 else if (is_ia32_SwitchJmp(pred)) {
256 else if (is_ia32_Cdq(pred) || is_ia32_Mulh(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_fDiv(pred)) {
269 if (nr == pn_Quot_res)
272 assert(0 && "there should be no more Projs for a fDiv");
274 else if (is_ia32_Call(pred)) {
277 else if (get_irn_mode(proj) == mode_X && nr == pn_Start_X_initial_exec) {
280 else if (is_Proj(pred)) {
281 first = get_Proj_pred(pred);
283 if (is_ia32_Call(first))
286 assert(0 && "unsupported proj-pos translation Proj(Proj)");
289 else if (get_irn_opcode(pred) == iro_Start) {
293 // assert(0 && "unsupported Proj(X)");