7ebba06d4166d5644a0ba7456d71afb05f5a0580
[libfirm] / ir / be / ia32 / bearch_ia32.c
1 /**
2  * This is the main ia32 firm backend driver.
3  *
4  * $Id$
5  */
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10
11 #ifdef _WIN32
12 #include <malloc.h>
13 #else
14 #include <alloca.h>
15 #endif
16
17 #include "pseudo_irg.h"
18 #include "irgwalk.h"
19 #include "irprog.h"
20 #include "irprintf.h"
21 #include "iredges_t.h"
22 #include "ircons.h"
23 #include "irgmod.h"
24 #include "irgopt.h"
25
26 #include "bitset.h"
27 #include "debug.h"
28
29 #include "../beabi.h"                 /* the general register allocator interface */
30 #include "../benode_t.h"
31 #include "../belower.h"
32 #include "../besched_t.h"
33 #include "../be.h"
34 #include "bearch_ia32_t.h"
35
36 #include "ia32_new_nodes.h"           /* ia32 nodes interface */
37 #include "gen_ia32_regalloc_if.h"     /* the generated interface (register type and class defenitions) */
38 #include "ia32_gen_decls.h"           /* interface declaration emitter */
39 #include "ia32_transform.h"
40 #include "ia32_emitter.h"
41 #include "ia32_map_regs.h"
42 #include "ia32_optimize.h"
43
44 #define DEBUG_MODULE "firm.be.ia32.isa"
45
46 /* TODO: ugly */
47 static set *cur_reg_set = NULL;
48
49 #undef is_Start
50 #define is_Start(irn) (get_irn_opcode(irn) == iro_Start)
51
52 ir_node *ia32_new_NoReg_gp(ia32_code_gen_t *cg) {
53         return be_abi_get_callee_save_irn(cg->birg->abi, &ia32_gp_regs[REG_XXX]);
54 }
55
56 ir_node *ia32_new_NoReg_fp(ia32_code_gen_t *cg) {
57         return be_abi_get_callee_save_irn(cg->birg->abi, &ia32_fp_regs[REG_XXXX]);
58 }
59
60 /**************************************************
61  *                         _ _              _  __
62  *                        | | |            (_)/ _|
63  *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
64  * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
65  * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
66  * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
67  *            __/ |
68  *           |___/
69  **************************************************/
70
71 static ir_node *my_skip_proj(const ir_node *n) {
72         while (is_Proj(n))
73                 n = get_Proj_pred(n);
74         return (ir_node *)n;
75 }
76
77 /**
78  * Return register requirements for an ia32 node.
79  * If the node returns a tuple (mode_T) then the proj's
80  * will be asked for this information.
81  */
82 static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos) {
83         const ia32_register_req_t *irn_req;
84         long                       node_pos = pos == -1 ? 0 : pos;
85         ir_mode                   *mode     = get_irn_mode(irn);
86         firm_dbg_module_t         *mod      = firm_dbg_register(DEBUG_MODULE);
87
88         if (mode == mode_T || mode == mode_M) {
89                 DBG((mod, LEVEL_1, "ignoring mode_T, mode_M node %+F\n", irn));
90                 return NULL;
91         }
92
93         DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));
94
95
96         if (is_Proj(irn)) {
97                 if (pos == -1) {
98                         node_pos = ia32_translate_proj_pos(irn);
99                 }
100                 else {
101                         node_pos = pos;
102                 }
103
104                 irn = my_skip_proj(irn);
105
106                 DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
107         }
108
109         if (is_ia32_irn(irn)) {
110                 if (pos >= 0) {
111                         irn_req = get_ia32_in_req(irn, pos);
112                 }
113                 else {
114                         irn_req = get_ia32_out_req(irn, node_pos);
115                 }
116
117                 DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", irn, pos));
118
119                 memcpy(req, &(irn_req->req), sizeof(*req));
120
121                 if (arch_register_req_is(&(irn_req->req), should_be_same)) {
122                         assert(irn_req->same_pos >= 0 && "should be same constraint for in -> out NYI");
123                         req->other_same = get_irn_n(irn, irn_req->same_pos);
124                 }
125
126                 if (arch_register_req_is(&(irn_req->req), should_be_different)) {
127                         assert(irn_req->different_pos >= 0 && "should be different constraint for in -> out NYI");
128                         req->other_different = get_irn_n(irn, irn_req->different_pos);
129                 }
130         }
131         else {
132                 /* treat Phi like Const with default requirements */
133                 if (is_Phi(irn)) {
134                         DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
135                         if (mode_is_float(mode))
136                                 memcpy(req, &(ia32_default_req_ia32_fp.req), sizeof(*req));
137                         else if (mode_is_int(mode) || mode_is_reference(mode))
138                                 memcpy(req, &(ia32_default_req_ia32_gp.req), sizeof(*req));
139                         else if (mode == mode_T || mode == mode_M) {
140                                 DBG((mod, LEVEL_1, "ignoring Phi node %+F\n", irn));
141                                 return NULL;
142                         }
143                         else
144                                 assert(0 && "unsupported Phi-Mode");
145                 }
146                 else {
147                         DB((mod, LEVEL_1, "returning NULL for %+F (not ia32)\n", irn));
148                         req = NULL;
149                 }
150         }
151
152         return req;
153 }
154
155 static void ia32_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
156         int                   pos = 0;
157         const ia32_irn_ops_t *ops = self;
158
159         DBG((ops->cg->mod, LEVEL_1, "ia32 assigned register %s to node %+F\n", reg->name, irn));
160
161         if (is_Proj(irn)) {
162                 pos = ia32_translate_proj_pos(irn);
163                 irn = my_skip_proj(irn);
164         }
165
166         if (is_ia32_irn(irn)) {
167                 const arch_register_t **slots;
168
169                 slots      = get_ia32_slots(irn);
170                 slots[pos] = reg;
171         }
172         else {
173                 ia32_set_firm_reg(irn, reg, cur_reg_set);
174         }
175 }
176
177 static const arch_register_t *ia32_get_irn_reg(const void *self, const ir_node *irn) {
178         int pos = 0;
179         const arch_register_t *reg = NULL;
180
181         if (is_Proj(irn)) {
182                 pos = ia32_translate_proj_pos(irn);
183                 irn = my_skip_proj(irn);
184         }
185
186         if (is_ia32_irn(irn)) {
187                 const arch_register_t **slots;
188                 slots = get_ia32_slots(irn);
189                 reg   = slots[pos];
190         }
191         else {
192                 reg = ia32_get_firm_reg(irn, cur_reg_set);
193         }
194
195         return reg;
196 }
197
198 static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) {
199         irn = my_skip_proj(irn);
200         if (is_cfop(irn))
201                 return arch_irn_class_branch;
202         else if (is_ia32_irn(irn))
203                 return arch_irn_class_normal;
204         else
205                 return 0;
206 }
207
208 static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
209         irn = my_skip_proj(irn);
210         if (is_ia32_irn(irn))
211                 return get_ia32_flags(irn);
212         else {
213                 return 0;
214         }
215 }
216
217 static entity *ia32_get_frame_entity(const void *self, const ir_node *irn) {
218         return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
219 }
220
221 static void ia32_set_stack_bias(const void *self, ir_node *irn, int bias) {
222         char buf[64];
223         const ia32_irn_ops_t *ops = self;
224
225         if (is_ia32_use_frame(irn) && bias != 0) {
226                 ia32_am_flavour_t am_flav = get_ia32_am_flavour(irn);
227
228                 DBG((ops->cg->mod, LEVEL_1, "stack biased %+F with %d\n", irn, bias));
229                 snprintf(buf, sizeof(buf), "%d", bias);
230                 add_ia32_am_offs(irn, buf);
231                 am_flav |= ia32_O;
232                 set_ia32_am_flavour(irn, am_flav);
233         }
234 }
235
236 typedef struct {
237         be_abi_call_flags_bits_t flags;
238         const arch_isa_t *isa;
239         ir_graph *irg;
240 } ia32_abi_env_t;
241
242 static void *ia32_abi_init(const be_abi_call_t *call, const arch_isa_t *isa, ir_graph *irg)
243 {
244         ia32_abi_env_t *env    = xmalloc(sizeof(env[0]));
245         be_abi_call_flags_t fl = be_abi_call_get_flags(call);
246         env->flags = fl.bits;
247         env->irg   = irg;
248         env->isa   = isa;
249         return env;
250 }
251
252 static void ia32_abi_dont_save_regs(void *self, pset *s)
253 {
254         ia32_abi_env_t *env = self;
255         if(env->flags.try_omit_fp)
256                 pset_insert_ptr(s, env->isa->bp);
257 }
258
259 static const arch_register_t *ia32_abi_prologue(void *self, pmap *reg_map)
260 {
261         ia32_abi_env_t *env = self;
262         return env->isa->bp;
263 }
264
265 static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map)
266 {
267 }
268
269 /**
270  * Produces the type which sits between the stack args and the locals on the stack.
271  * it will contain the return address and space to store the old base pointer.
272  * @return The Firm type modeling the ABI between type.
273  */
274 static ir_type *ia32_abi_get_between_type(void *self)
275 {
276         static ir_type *omit_fp_between_type = NULL;
277         static ir_type *between_type         = NULL;
278
279         ia32_abi_env_t *env = self;
280
281         if(!between_type) {
282                 entity *old_bp_ent;
283                 entity *ret_addr_ent;
284                 entity *omit_fp_ret_addr_ent;
285
286                 ir_type *old_bp_type   = new_type_primitive(new_id_from_str("bp"), mode_P);
287                 ir_type *ret_addr_type = new_type_primitive(new_id_from_str("return_addr"), mode_P);
288
289                 between_type           = new_type_class(new_id_from_str("ia32_between_type"));
290                 old_bp_ent             = new_entity(between_type, new_id_from_str("old_bp"), old_bp_type);
291                 ret_addr_ent           = new_entity(between_type, new_id_from_str("ret_addr"), ret_addr_type);
292
293                 set_entity_offset_bytes(old_bp_ent, 0);
294                 set_entity_offset_bytes(ret_addr_ent, get_type_size_bytes(old_bp_type));
295                 set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));
296
297                 omit_fp_between_type   = new_type_class(new_id_from_str("ia32_between_type_omit_fp"));
298                 omit_fp_ret_addr_ent   = new_entity(omit_fp_between_type, new_id_from_str("ret_addr"), ret_addr_type);
299
300                 set_entity_offset_bytes(omit_fp_ret_addr_ent, 0);
301                 set_type_size_bytes(omit_fp_between_type, get_type_size_bytes(ret_addr_type));
302         }
303
304         return env->flags.try_omit_fp ? omit_fp_between_type : between_type;
305 }
306
307 static const be_abi_callbacks_t ia32_abi_callbacks = {
308         ia32_abi_init,
309         free,
310         ia32_abi_get_between_type,
311         ia32_abi_dont_save_regs,
312         ia32_abi_prologue,
313         ia32_abi_epilogue,
314 };
315
316 /* fill register allocator interface */
317
318 static const arch_irn_ops_if_t ia32_irn_ops_if = {
319         ia32_get_irn_reg_req,
320         ia32_set_irn_reg,
321         ia32_get_irn_reg,
322         ia32_classify,
323         ia32_get_flags,
324         ia32_get_frame_entity,
325         ia32_set_stack_bias
326 };
327
328 ia32_irn_ops_t ia32_irn_ops = {
329         &ia32_irn_ops_if,
330         NULL
331 };
332
333
334
335 /**************************************************
336  *                _                         _  __
337  *               | |                       (_)/ _|
338  *   ___ ___   __| | ___  __ _  ___ _ __    _| |_
339  *  / __/ _ \ / _` |/ _ \/ _` |/ _ \ '_ \  | |  _|
340  * | (_| (_) | (_| |  __/ (_| |  __/ | | | | | |
341  *  \___\___/ \__,_|\___|\__, |\___|_| |_| |_|_|
342  *                        __/ |
343  *                       |___/
344  **************************************************/
345
346 /**
347  * Transforms the standard firm graph into
348  * an ia32 firm graph
349  */
350 static void ia32_prepare_graph(void *self) {
351         ia32_code_gen_t *cg = self;
352         firm_dbg_module_t *old_mod = cg->mod;
353
354         cg->mod = firm_dbg_register("firm.be.ia32.transform");
355         irg_walk_blkwise_graph(cg->irg, ia32_place_consts_set_modes, ia32_transform_node, cg);
356         be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
357
358         edges_deactivate(cg->irg);
359         dead_node_elimination(cg->irg);
360         edges_activate(cg->irg);
361
362         cg->mod = old_mod;
363
364         if (cg->opt.doam) {
365                 irg_walk_blkwise_graph(cg->irg, NULL, ia32_optimize_am, cg);
366                 be_dump(cg->irg, "-am", dump_ir_block_graph_sched);
367         }
368 }
369
370
371 /**
372  * Insert copies for all ia32 nodes where the should_be_same requirement
373  * is not fulfilled.
374  * Transform Sub into Neg -- Add if IN2 == OUT
375  */
376 static void ia32_finish_irg_walker(ir_node *irn, void *env) {
377         ia32_code_gen_t            *cg = env;
378         const ia32_register_req_t **reqs;
379         const arch_register_t      *out_reg, *in_reg;
380         int                         n_res, i;
381         ir_node                    *copy, *in_node, *block;
382
383         if (! is_ia32_irn(irn))
384                 return;
385
386         /* nodes with destination address mode don't produce values */
387         if (get_ia32_op_type(irn) == ia32_AddrModeD)
388                 return;
389
390         reqs  = get_ia32_out_req_all(irn);
391         n_res = get_ia32_n_res(irn);
392         block = get_nodes_block(irn);
393
394         /* check all OUT requirements, if there is a should_be_same */
395         for (i = 0; i < n_res; i++) {
396                 if (arch_register_req_is(&(reqs[i]->req), should_be_same)) {
397                         /* get in and out register */
398                         out_reg = get_ia32_out_reg(irn, i);
399                         in_node = get_irn_n(irn, reqs[i]->same_pos);
400                         in_reg  = arch_get_irn_register(cg->arch_env, in_node);
401
402                         /* check if in and out register are equal */
403                         if (arch_register_get_index(out_reg) != arch_register_get_index(in_reg)) {
404                                 DBG((cg->mod, LEVEL_1, "inserting copy for %+F in_pos %d\n", irn, reqs[i]->same_pos));
405
406                                 /* create copy from in register */
407                                 copy = be_new_Copy(arch_register_get_class(in_reg), cg->irg, block, in_node);
408
409                                 /* destination is the out register */
410                                 arch_set_irn_register(cg->arch_env, copy, out_reg);
411
412                                 /* insert copy before the node into the schedule */
413                                 sched_add_before(irn, copy);
414
415                                 /* set copy as in */
416                                 set_irn_n(irn, reqs[i]->same_pos, copy);
417                         }
418                 }
419         }
420
421         /* check if there is a sub which need to be transformed */
422         ia32_transform_sub_to_neg_add(irn, cg);
423 }
424
425 /**
426  * Add Copy nodes for not fulfilled should_be_equal constraints
427  */
428 static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
429         irg_walk_blkwise_graph(irg, NULL, ia32_finish_irg_walker, cg);
430 }
431
432
433
434 /**
435  * Dummy functions for hooks we don't need but which must be filled.
436  */
437 static void ia32_before_sched(void *self) {
438 }
439
440 static void ia32_before_ra(void *self) {
441 }
442
443
444
445 /**
446  * Transforms a be node into a Load.
447  */
448 static void transform_to_Load(ia32_transform_env_t *env) {
449         ir_node *irn         = env->irn;
450         entity  *ent         = be_get_frame_entity(irn);
451         ir_mode *mode        = env->mode;
452         ir_node *noreg       = ia32_new_NoReg_gp(env->cg);
453         ir_node *nomem       = new_rd_NoMem(env->irg);
454         ir_node *sched_point = NULL;
455         ir_node *ptr         = get_irn_n(irn, 0);
456         ir_node *mem         = be_is_Reload(irn) ? get_irn_n(irn, 1) : nomem;
457         ir_node *new_op, *proj;
458         const arch_register_t *reg;
459
460         if (sched_is_scheduled(irn)) {
461                 sched_point = sched_prev(irn);
462         }
463
464         if (mode_is_float(mode)) {
465                 new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
466         }
467         else {
468                 new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
469         }
470
471         set_ia32_am_support(new_op, ia32_am_Source);
472         set_ia32_op_type(new_op, ia32_AddrModeS);
473         set_ia32_am_flavour(new_op, ia32_B);
474         set_ia32_ls_mode(new_op, mode);
475         set_ia32_frame_ent(new_op, ent);
476         set_ia32_use_frame(new_op);
477
478         proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode, pn_Load_res);
479
480         if (sched_point) {
481                 sched_add_after(sched_point, new_op);
482                 sched_add_after(new_op, proj);
483
484                 sched_remove(irn);
485         }
486
487         /* copy the register from the old node to the new Load */
488         reg = arch_get_irn_register(env->cg->arch_env, irn);
489         arch_set_irn_register(env->cg->arch_env, new_op, reg);
490
491         exchange(irn, proj);
492
493 }
494
495 /**
496  * Transforms a be node into a Store.
497  */
498 static void transform_to_Store(ia32_transform_env_t *env) {
499         ir_node *irn   = env->irn;
500         entity  *ent   = be_get_frame_entity(irn);
501         ir_mode *mode  = env->mode;
502         ir_node *noreg = ia32_new_NoReg_gp(env->cg);
503         ir_node *nomem = new_rd_NoMem(env->irg);
504         ir_node *ptr   = get_irn_n(irn, 0);
505         ir_node *val   = get_irn_n(irn, 1);
506         ir_node *new_op, *proj;
507         ir_node *sched_point = NULL;
508
509         if (sched_is_scheduled(irn)) {
510                 sched_point = sched_prev(irn);
511         }
512
513         if (mode_is_float(mode)) {
514                 new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, val, nomem, mode_T);
515         }
516         else {
517                 new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, nomem, mode_T);
518         }
519
520         set_ia32_am_support(new_op, ia32_am_Dest);
521         set_ia32_op_type(new_op, ia32_AddrModeD);
522         set_ia32_am_flavour(new_op, ia32_B);
523         set_ia32_ls_mode(new_op, get_irn_mode(val));
524         set_ia32_frame_ent(new_op, ent);
525         set_ia32_use_frame(new_op);
526
527         proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode, 0);
528
529         if (sched_point) {
530                 sched_add_after(sched_point, new_op);
531                 sched_add_after(new_op, proj);
532
533                 sched_remove(irn);
534         }
535
536         exchange(irn, proj);
537
538 }
539
540 /**
541  * Calls the transform functions for StackParam, Spill and Reload.
542  */
543 static void ia32_after_ra_walker(ir_node *node, void *env) {
544         ia32_code_gen_t *cg = env;
545         ia32_transform_env_t tenv;
546
547         if (is_Block(node))
548                 return;
549
550         tenv.block = get_nodes_block(node);
551         tenv.dbg   = get_irn_dbg_info(node);
552         tenv.irg   = current_ir_graph;
553         tenv.irn   = node;
554         tenv.mod   = cg->mod;
555         tenv.mode  = get_irn_mode(node);
556         tenv.cg    = cg;
557
558         /* be_is_StackParam(node) || */
559         if (be_is_Reload(node)) {
560                 transform_to_Load(&tenv);
561         }
562         else if (be_is_Spill(node)) {
563                 transform_to_Store(&tenv);
564         }
565 }
566
567 /**
568  * We transform StackParam, Spill and Reload here. This needs to be done before
569  * stack biasing otherwise we would miss the corrected offset for these nodes.
570  */
571 static void ia32_after_ra(void *self) {
572         ia32_code_gen_t *cg = self;
573         irg_walk_blkwise_graph(cg->irg, NULL, ia32_after_ra_walker, self);
574 }
575
576
577 /**
578  * Emits the code, closes the output file and frees
579  * the code generator interface.
580  */
581 static void ia32_codegen(void *self) {
582         ia32_code_gen_t *cg = self;
583         ir_graph        *irg = cg->irg;
584         FILE            *out = cg->out;
585
586         if (cg->emit_decls) {
587                 ia32_gen_decls(cg->out);
588                 cg->emit_decls = 0;
589         }
590
591         ia32_finish_irg(irg, cg);
592         be_dump(irg, "-finished", dump_ir_block_graph_sched);
593         ia32_gen_routine(out, irg, cg);
594
595         cur_reg_set = NULL;
596
597         pmap_destroy(cg->tv_ent);
598         pmap_destroy(cg->types);
599
600         /* de-allocate code generator */
601         del_set(cg->reg_set);
602         free(self);
603 }
604
605 static void *ia32_cg_init(FILE *F, const be_irg_t *birg);
606
607 static const arch_code_generator_if_t ia32_code_gen_if = {
608         ia32_cg_init,
609         NULL,                /* before abi introduce hook */
610         ia32_prepare_graph,
611         ia32_before_sched,   /* before scheduling hook */
612         ia32_before_ra,      /* before register allocation hook */
613         ia32_after_ra,       /* after register allocation hook */
614         ia32_codegen         /* emit && done */
615 };
616
617 /**
618  * Initializes the code generator.
619  */
620 static void *ia32_cg_init(FILE *F, const be_irg_t *birg) {
621         ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env->isa;
622         ia32_code_gen_t *cg  = xcalloc(1, sizeof(*cg));
623
624         cg->impl     = &ia32_code_gen_if;
625         cg->irg      = birg->irg;
626         cg->reg_set  = new_set(ia32_cmp_irn_reg_assoc, 1024);
627         cg->mod      = firm_dbg_register("firm.be.ia32.cg");
628         cg->out      = F;
629         cg->arch_env = birg->main_env->arch_env;
630         cg->types    = pmap_create();
631         cg->tv_ent   = pmap_create();
632         cg->birg     = birg;
633
634         /* set optimizations */
635         cg->opt.incdec    = 0;
636         cg->opt.doam      = 1;
637         cg->opt.placecnst = 1;
638         cg->opt.immops    = 1;
639
640 #ifndef NDEBUG
641         if (isa->name_obst_size) {
642                 //printf("freed %d bytes from name obst\n", isa->name_obst_size);
643                 isa->name_obst_size = 0;
644                 obstack_free(isa->name_obst, NULL);
645                 obstack_init(isa->name_obst);
646         }
647 #endif /* NDEBUG */
648
649         isa->num_codegens++;
650
651         if (isa->num_codegens > 1)
652                 cg->emit_decls = 0;
653         else
654                 cg->emit_decls = 1;
655
656         cur_reg_set = cg->reg_set;
657
658         ia32_irn_ops.cg = cg;
659
660         return (arch_code_generator_t *)cg;
661 }
662
663
664
665 /*****************************************************************
666  *  ____             _                  _   _____  _____
667  * |  _ \           | |                | | |_   _|/ ____|  /\
668  * | |_) | __ _  ___| | _____ _ __   __| |   | | | (___   /  \
669  * |  _ < / _` |/ __| |/ / _ \ '_ \ / _` |   | |  \___ \ / /\ \
670  * | |_) | (_| | (__|   <  __/ | | | (_| |  _| |_ ____) / ____ \
671  * |____/ \__,_|\___|_|\_\___|_| |_|\__,_| |_____|_____/_/    \_\
672  *
673  *****************************************************************/
674
675 static ia32_isa_t ia32_isa_template = {
676         &ia32_isa_if,            /* isa interface implementation */
677         &ia32_gp_regs[REG_ESP],  /* stack pointer register */
678         &ia32_gp_regs[REG_EBP],  /* base pointer register */
679         -1,                      /* stack direction */
680         0,                       /* number of code generator objects so far */
681         NULL,                    /* 16bit register names */
682         NULL,                    /* 8bit register names */
683 #ifndef NDEBUG
684         NULL,                    /* name obstack */
685         0                        /* name obst size */
686 #endif
687 };
688
689 /**
690  * Initializes the backend ISA.
691  */
692 static void *ia32_init(void) {
693         static int inited = 0;
694         ia32_isa_t *isa;
695
696         if(inited)
697                 return NULL;
698
699         isa = xcalloc(1, sizeof(*isa));
700         memcpy(isa, &ia32_isa_template, sizeof(*isa));
701
702         ia32_register_init(isa);
703         ia32_create_opcodes();
704
705         isa->regs_16bit = pmap_create();
706         isa->regs_8bit  = pmap_create();
707
708         ia32_build_16bit_reg_map(isa->regs_16bit);
709         ia32_build_8bit_reg_map(isa->regs_8bit);
710
711 #ifndef NDEBUG
712         isa->name_obst = xcalloc(1, sizeof(*(isa->name_obst)));
713         obstack_init(isa->name_obst);
714         isa->name_obst_size = 0;
715 #endif /* NDEBUG */
716
717         inited = 1;
718
719         return isa;
720 }
721
722
723
724 /**
725  * Closes the output file and frees the ISA structure.
726  */
727 static void ia32_done(void *self) {
728         ia32_isa_t *isa = self;
729
730         pmap_destroy(isa->regs_16bit);
731         pmap_destroy(isa->regs_8bit);
732
733 #ifndef NDEBUG
734         //printf("name obst size = %d bytes\n", isa->name_obst_size);
735         obstack_free(isa->name_obst, NULL);
736 #endif /* NDEBUG */
737
738         free(self);
739 }
740
741
742
743 static int ia32_get_n_reg_class(const void *self) {
744         return N_CLASSES;
745 }
746
747 static const arch_register_class_t *ia32_get_reg_class(const void *self, int i) {
748         assert(i >= 0 && i < N_CLASSES && "Invalid ia32 register class requested.");
749         return &ia32_reg_classes[i];
750 }
751
752 /**
753  * Get the register class which shall be used to store a value of a given mode.
754  * @param self The this pointer.
755  * @param mode The mode in question.
756  * @return A register class which can hold values of the given mode.
757  */
758 const arch_register_class_t *ia32_get_reg_class_for_mode(const void *self, const ir_mode *mode) {
759         if (mode_is_float(mode))
760                 return &ia32_reg_classes[CLASS_ia32_fp];
761         else
762                 return &ia32_reg_classes[CLASS_ia32_gp];
763 }
764
765 /**
766  * Get the ABI restrictions for procedure calls.
767  * @param self        The this pointer.
768  * @param method_type The type of the method (procedure) in question.
769  * @param abi         The abi object to be modified
770  */
771 void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi) {
772         ir_type  *tp;
773         ir_mode  *mode;
774         unsigned  cc        = get_method_calling_convention(method_type);
775         int       n         = get_method_n_params(method_type);
776         int       biggest_n = -1;
777         int       stack_idx = 0;
778         int       i, ignore;
779         ir_mode **modes;
780         const arch_register_t *reg;
781         be_abi_call_flags_t call_flags;
782
783         /* set abi flags for calls */
784         call_flags.bits.left_to_right         = 0;
785         call_flags.bits.store_args_sequential = 0;
786         call_flags.bits.try_omit_fp           = 1;
787         call_flags.bits.fp_free               = 0;
788         call_flags.bits.call_has_imm          = 1;
789
790         /* set stack parameter passing style */
791         be_abi_call_set_flags(abi, call_flags, &ia32_abi_callbacks);
792
793         /* collect the mode for each type */
794         modes = alloca(n * sizeof(modes[0]));
795
796         for (i = 0; i < n; i++) {
797                 tp       = get_method_param_type(method_type, i);
798                 modes[i] = get_type_mode(tp);
799         }
800
801         /* set register parameters  */
802         if (cc & cc_reg_param) {
803                 /* determine the number of parameters passed via registers */
804                 biggest_n = ia32_get_n_regparam_class(n, modes, &ignore, &ignore);
805
806                 /* loop over all parameters and set the register requirements */
807                 for (i = 0; i <= biggest_n; i++) {
808                         reg = ia32_get_RegParam_reg(n, modes, i, cc);
809                         assert(reg && "kaputt");
810                         be_abi_call_param_reg(abi, i, reg);
811                 }
812
813                 stack_idx = i;
814         }
815
816
817         /* set stack parameters */
818         for (i = stack_idx; i < n; i++) {
819                 be_abi_call_param_stack(abi, i);
820         }
821
822
823         /* set return registers */
824         n = get_method_n_ress(method_type);
825
826         assert(n <= 2 && "more than two results not supported");
827
828         /* In case of 64bit returns, we will have two 32bit values */
829         if (n == 2) {
830                 tp   = get_method_res_type(method_type, 0);
831                 mode = get_type_mode(tp);
832
833                 assert(!mode_is_float(mode) && "two FP results not supported");
834
835                 tp   = get_method_res_type(method_type, 1);
836                 mode = get_type_mode(tp);
837
838                 assert(!mode_is_float(mode) && "two FP results not supported");
839
840                 be_abi_call_res_reg(abi, 0, &ia32_gp_regs[REG_EAX]);
841                 be_abi_call_res_reg(abi, 1, &ia32_gp_regs[REG_EDX]);
842         }
843         else if (n == 1) {
844                 tp   = get_method_res_type(method_type, 0);
845                 assert(is_atomic_type(tp));
846                 mode = get_type_mode(tp);
847
848                 be_abi_call_res_reg(abi, 0, mode_is_float(mode) ? &ia32_fp_regs[REG_XMM0] : &ia32_gp_regs[REG_EAX]);
849         }
850 }
851
852
853 static const void *ia32_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn) {
854         return &ia32_irn_ops;
855 }
856
857 const arch_irn_handler_t ia32_irn_handler = {
858         ia32_get_irn_ops
859 };
860
861 const arch_irn_handler_t *ia32_get_irn_handler(const void *self) {
862         return &ia32_irn_handler;
863 }
864
865 int ia32_to_appear_in_schedule(void *block_env, const ir_node *irn) {
866         return is_ia32_irn(irn);
867 }
868
869 /**
870  * Initializes the code generator interface.
871  */
872 static const arch_code_generator_if_t *ia32_get_code_generator_if(void *self) {
873         return &ia32_code_gen_if;
874 }
875
876 list_sched_selector_t ia32_sched_selector;
877
878 /**
879  * Returns the reg_pressure scheduler with to_appear_in_schedule() overloaded
880  */
881 static const list_sched_selector_t *ia32_get_list_sched_selector(const void *self) {
882         memcpy(&ia32_sched_selector, trivial_selector, sizeof(list_sched_selector_t));
883         ia32_sched_selector.to_appear_in_schedule = ia32_to_appear_in_schedule;
884         return &ia32_sched_selector;
885 }
886
887 #ifdef WITH_LIBCORE
888 static void ia32_register_options(lc_opt_entry_t *ent)
889 {
890 }
891 #endif /* WITH_LIBCORE */
892
893 const arch_isa_if_t ia32_isa_if = {
894 #ifdef WITH_LIBCORE
895         ia32_register_options,
896 #endif
897         ia32_init,
898         ia32_done,
899         ia32_get_n_reg_class,
900         ia32_get_reg_class,
901         ia32_get_reg_class_for_mode,
902         ia32_get_call_abi,
903         ia32_get_irn_handler,
904         ia32_get_code_generator_if,
905         ia32_get_list_sched_selector
906 };