remove arch_irn_class_is macro as it hides usages of arch_irn_class_XXX from grep...
[libfirm] / ir / be / ppc32 / ppc32_emitter.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   ppc emitter
23  * @author  Moritz Kroll, Jens Mueller
24  * @version $Id$
25  */
26 #include "config.h"
27
28 #include <limits.h>
29
30 #include "xmalloc.h"
31 #include "tv.h"
32 #include "iredges.h"
33 #include "debug.h"
34 #include "irgwalk.h"
35 #include "irprintf.h"
36 #include "irop_t.h"
37 #include "irnode_t.h"
38 #include "irargs_t.h"
39 #include "error.h"
40
41 #include "../besched.h"
42 #include "../benode.h"
43 #include "../begnuas.h"
44
45 #include "ppc32_emitter.h"
46 #include "gen_ppc32_emitter.h"
47 #include "gen_ppc32_regalloc_if.h"
48 #include "ppc32_nodes_attr.h"
49 #include "ppc32_new_nodes.h"
50 #include "ppc32_map_regs.h"
51
52 #define SNPRINTF_BUF_LEN 128
53
54 static char printbuf[SNPRINTF_BUF_LEN];
55
56 extern int isleaf;
57
58
59 /*************************************************************
60  *             _       _    __   _          _
61  *            (_)     | |  / _| | |        | |
62  *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
63  * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
64  * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
65  * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
66  * | |                                       | |
67  * |_|                                       |_|
68  *************************************************************/
69 /**
70  * Returns the register at in position pos.
71  */
72 static const arch_register_t *get_in_reg(const ir_node *irn, int pos)
73 {
74         ir_node                *op;
75         const arch_register_t  *reg = NULL;
76
77         assert(get_irn_arity(irn) > pos && "Invalid IN position");
78
79         /* The out register of the operator at position pos is the
80            in register we need. */
81         op = get_irn_n(irn, pos);
82
83         reg = arch_get_irn_register(op);
84
85         assert(reg && "no in register found");
86         return reg;
87 }
88
89 /**
90  * Returns the register at out position pos.
91  */
92 static const arch_register_t *get_out_reg(const ir_node *irn, int pos)
93 {
94         ir_node                *proj;
95         const arch_register_t  *reg = NULL;
96
97         assert(get_irn_n_edges(irn) > pos && "Invalid OUT position");
98
99         /* 1st case: irn is not of mode_T, so it has only                 */
100         /*           one OUT register -> good                             */
101         /* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
102         /*           Proj with the corresponding projnum for the register */
103
104         if (get_irn_mode(irn) != mode_T) {
105                 reg = arch_get_irn_register(irn);
106         } else if (is_ppc32_irn(irn)) {
107                 reg = arch_irn_get_register(irn, pos);
108         } else {
109                 const ir_edge_t *edge;
110
111                 foreach_out_edge(irn, edge) {
112                         proj = get_edge_src_irn(edge);
113                         assert(is_Proj(proj) && "non-Proj from mode_T node");
114                         if (get_Proj_proj(proj) == pos) {
115                                 reg = arch_get_irn_register(proj);
116                                 break;
117                         }
118                 }
119         }
120
121         assert(reg && "no out register found");
122         return reg;
123 }
124
125 /**
126  * Emit the name of the source register at given input position.
127  */
128 void ppc32_emit_source_register(const ir_node *node, int pos)
129 {
130         const arch_register_t *reg = get_in_reg(node, pos);
131         be_emit_string(arch_register_get_name(reg));
132 }
133
134 /**
135  * Emit the name of the destination register at given output position.
136  */
137 void ppc32_emit_dest_register(const ir_node *node, int pos)
138 {
139         const arch_register_t *reg = get_out_reg(node, pos);
140         be_emit_string(arch_register_get_name(reg));
141 }
142
143 void ppc32_emit_rlwimi_helper(const ir_node *n)
144 {
145         const rlwimi_const_t *rlwimi_const = get_ppc32_rlwimi_const(n);
146
147         be_emit_irprintf("%i, %i, %i", rlwimi_const->shift,
148                 rlwimi_const->maskA, rlwimi_const->maskB);
149 }
150
151 /**
152  * Emit a const or symconst.
153  */
154 void ppc32_emit_immediate(const ir_node *n)
155 {
156         const char *buf;
157
158         switch (get_ppc32_type(n)) {
159         case ppc32_ac_Const:
160                 tarval_snprintf(printbuf, SNPRINTF_BUF_LEN, get_ppc32_constant_tarval(n));
161                 buf = printbuf;
162                 break;
163         case ppc32_ac_SymConst:
164                 buf = get_id_str(get_ppc32_symconst_ident(n));
165                 break;
166         case ppc32_ac_Offset:
167                 be_emit_irprintf("%i", get_ppc32_offset(n));
168                 return;
169         default:
170                 assert(0 && "node_const_to_str(): Illegal offset type");
171                 return;
172         }
173         switch (get_ppc32_offset_mode(n)) {
174         case ppc32_ao_None:
175                 be_emit_string(buf);
176                 return;
177         case ppc32_ao_Lo16:
178                 be_emit_irprintf("lo16(%s)", buf);
179                 return;
180         case ppc32_ao_Hi16:
181                 be_emit_irprintf("hi16(%s)", buf);
182                 return;
183         case ppc32_ao_Ha16:
184                 be_emit_irprintf("ha16(%s)", buf);
185                 return;
186         default:
187                 assert(0 && "node_const_to_str(): Illegal offset mode");
188                 return;
189         }
190 }
191
192 /**
193  * Emits a node's offset.
194  */
195 void ppc32_emit_offset(const ir_node *n)
196 {
197         const char *buf;
198         if (get_ppc32_type(n) == ppc32_ac_None) {
199                 be_emit_char('0');
200                 return;
201         }
202
203         switch (get_ppc32_type(n)) {
204         case ppc32_ac_Const:
205                 tarval_snprintf(printbuf, SNPRINTF_BUF_LEN, get_ppc32_constant_tarval(n));
206                 buf = printbuf;
207                 break;
208         case ppc32_ac_SymConst:
209                 buf = get_id_str(get_ppc32_symconst_ident(n));
210                 break;
211         case ppc32_ac_Offset:
212                 be_emit_irprintf("%i", get_ppc32_offset(n));
213                 return;
214         default:
215                 assert(0 && "node_offset_to_str(): Illegal offset type");
216                 return;
217         }
218         switch (get_ppc32_offset_mode(n)) {
219         case ppc32_ao_None:
220                 be_emit_string(buf);
221                 return;
222         case ppc32_ao_Lo16:
223                 be_emit_irprintf("lo16(%s)", buf);
224                 return;
225         case ppc32_ao_Hi16:
226                 be_emit_irprintf("hi16(%s)", buf);
227                 return;
228         case ppc32_ao_Ha16:
229                 be_emit_irprintf("ha16(%s)", buf);
230                 return;
231         default:
232                 assert(0 && "node_offset_to_str(): Illegal offset mode");
233                 return;
234         }
235 }
236
237 /**
238  * Emits code for a unconditional jump.
239  */
240 static void emit_Jmp(const ir_node *irn)
241 {
242         ir_node *block = get_nodes_block(irn);
243
244         if (get_irn_link(irn) != get_irn_link(block)) {
245                 ir_node *dest = get_irn_link(irn);
246                 be_emit_cstring("\tb ");
247                 be_gas_emit_block_name(dest);
248         } else {
249                 be_emit_irprintf("/* fallthrough(%+F) */", get_irn_link(irn));
250         }
251         be_emit_finish_line_gas(irn);
252 }
253
254 /**
255  * Emits code for a call
256  */
257 static void emit_be_Call(const ir_node *irn)
258 {
259         ir_entity *call_ent = be_Call_get_entity(irn);
260
261         if (call_ent) {
262                 be_emit_irprintf("\tbl %s", get_entity_ld_name(call_ent));
263         } else {
264                 be_emit_cstring("\tmtlr ");
265                 ppc32_emit_source_register(irn, be_pos_Call_ptr);
266                 be_emit_pad_comment();
267                 be_emit_cstring("/* Move to link register and link */\n");
268                 be_emit_write_line();
269                 be_emit_cstring("\tblrl");
270         }
271         be_emit_finish_line_gas(irn);
272 }
273
274 static void emit_ppc32_Branch(const ir_node *irn)
275 {
276         static const char *branchops[8] = { 0, "beq", "blt", "ble", "bgt", "bge", "bne", "b" };
277         int projnum = get_ppc32_proj_nr(irn);
278
279         const ir_edge_t *edge = get_irn_out_edge_first(irn);
280         ir_node *proj = get_edge_src_irn(edge);
281
282         int opind;
283
284         if (get_Proj_proj(proj) == pn_Cond_true)
285                 opind = projnum;
286         else
287                 opind = 7 - projnum;
288
289         assert(opind>=0 && opind<8);
290
291         if (opind){
292                 be_emit_irprintf("\t%8s", branchops[opind]);
293                 ppc32_emit_source_register(irn, 0);
294                 be_emit_cstring(", ");
295                 be_gas_emit_block_name(get_irn_link(proj));
296                 be_emit_finish_line_gas(irn);
297         }
298
299         edge = get_irn_out_edge_next(irn, edge);
300         if (edge) {
301                 ir_node *blk = get_edge_src_irn(edge);
302                 be_emit_cstring("\tb ");
303                 be_gas_emit_block_name(get_irn_link(blk));
304                 be_emit_finish_line_gas(irn);
305         }
306 }
307
308 static void emit_ppc32_LoopCopy(const ir_node *irn)
309 {
310         be_emit_irprintf("LOOP_%ld:\n", get_irn_node_nr(irn));
311         be_emit_write_line();
312
313         be_emit_cstring("\tlwzu ");
314         ppc32_emit_dest_register(irn, 4);
315         be_emit_cstring(", 4(");
316         ppc32_emit_source_register(irn, 1);
317         be_emit_char(')');
318         be_emit_pad_comment();
319         be_emit_cstring("/* Load with update */\n");
320         be_emit_write_line();
321
322         be_emit_cstring("\tstwu ");
323         ppc32_emit_dest_register(irn, 4);
324         be_emit_cstring(", 4(");
325         ppc32_emit_source_register(irn, 2);
326         be_emit_char(')');
327         be_emit_pad_comment();
328         be_emit_cstring("/* Store with update */\n");
329         be_emit_write_line();
330
331         be_emit_irprintf("\tbdnz LOOP_%i", get_irn_node_nr(irn));
332         be_emit_finish_line_gas(irn);
333 }
334
335 static void emit_ppc32_Switch(const ir_node *irn)
336 {
337         ir_node *proj, *defproj = NULL;
338         int pn;
339
340         const ir_edge_t* edge;
341         foreach_out_edge(irn, edge) {
342                 proj = get_edge_src_irn(edge);
343                 assert(is_Proj(proj) && "Only proj allowed at Switch");
344                 if (get_irn_mode(proj) != mode_X) continue;
345
346                 pn = get_Proj_proj(proj);
347                 /* check for default proj */
348                 if (pn == get_ppc32_proj_nr(irn)) {
349                         assert(defproj == NULL && "found two defProjs at Switch");
350                         defproj = proj;
351                 } else {
352                         be_emit_cstring("\taddis ");
353                         ppc32_emit_source_register(irn, 1);
354                         be_emit_irprintf(", 0, hi16(%i)", pn);
355                         be_emit_pad_comment();
356                         be_emit_cstring("/* Load upper immediate */\n");
357                         be_emit_write_line();
358
359                         be_emit_cstring("\tori ");
360                         ppc32_emit_source_register(irn, 1);
361                         be_emit_cstring(", ");
362                         ppc32_emit_source_register(irn, 1);
363                         be_emit_irprintf(", lo16(%i)", pn);
364                         be_emit_pad_comment();
365                         be_emit_cstring("/* Load lower immediate */\n");
366                         be_emit_write_line();
367
368                         be_emit_cstring("\tcmp ");
369                         ppc32_emit_source_register(irn, 2);
370                         be_emit_cstring(", ");
371                         ppc32_emit_source_register(irn, 0);
372                         be_emit_cstring(", ");
373                         ppc32_emit_source_register(irn, 1);
374                         be_emit_pad_comment();
375                         be_emit_cstring("/* Compare */\n");
376                         be_emit_write_line();
377
378                         be_emit_cstring("\tbeq ");
379                         ppc32_emit_source_register(irn, 2);
380                         be_emit_cstring(", ");
381                         be_gas_emit_block_name(get_irn_link(proj));
382                         be_emit_cstring("/* Branch if equal */\n");
383                         be_emit_write_line();
384                 }
385         }
386         assert(defproj != NULL && "didn't find defProj at Switch");
387         be_emit_cstring("\tb ");
388         be_gas_emit_block_name(get_irn_link(defproj));
389         be_emit_finish_line_gas(irn);
390 }
391
392 /**
393  * Emits code for a backend Copy node
394  */
395 static void emit_be_Copy(const ir_node *irn)
396 {
397         const arch_register_class_t *regclass = arch_get_irn_reg_class(irn, 0);
398
399         if (regclass == &ppc32_reg_classes[CLASS_ppc32_gp]) {
400                 be_emit_cstring("\tmr ");
401         } else if (regclass == &ppc32_reg_classes[CLASS_ppc32_fp]) {
402                 be_emit_cstring("\tfmr ");
403         } else if (regclass == &ppc32_reg_classes[CLASS_ppc32_condition]) {
404                 be_emit_cstring("\tmcrf ");
405         } else {
406                 panic("ppc32 Emitter: Illegal register class for Copy");
407         }
408         ppc32_emit_dest_register(irn, 0);
409         be_emit_cstring(", ");
410         ppc32_emit_source_register(irn, 0);
411         be_emit_finish_line_gas(irn);
412 }
413
414 /**
415  * Emits code for a backend Perm node
416  */
417 static void emit_be_Perm(const ir_node *irn)
418 {
419         const arch_register_class_t *regclass = arch_get_irn_reg_class(irn, 0);
420
421         if (regclass == &ppc32_reg_classes[CLASS_ppc32_gp]) {
422                 be_emit_cstring("\txor ");
423                 ppc32_emit_source_register(irn, 0);
424                 be_emit_cstring(", ");
425                 ppc32_emit_source_register(irn, 0);
426                 be_emit_cstring(", ");
427                 ppc32_emit_source_register(irn, 1);
428                 be_emit_pad_comment();
429                 be_emit_cstring("/* Swap with XOR */\n");
430                 be_emit_write_line();
431
432                 be_emit_cstring("\txor ");
433                 ppc32_emit_source_register(irn, 1);
434                 be_emit_cstring(", ");
435                 ppc32_emit_source_register(irn, 0);
436                 be_emit_cstring(", ");
437                 ppc32_emit_source_register(irn, 1);
438                 be_emit_pad_comment();
439                 be_emit_cstring("/* (continued) */\n");
440                 be_emit_write_line();
441
442                 be_emit_cstring("\txor ");
443                 ppc32_emit_source_register(irn, 0);
444                 be_emit_cstring(", ");
445                 ppc32_emit_source_register(irn, 0);
446                 be_emit_cstring(", ");
447                 ppc32_emit_source_register(irn, 1);
448         } else if (regclass == &ppc32_reg_classes[CLASS_ppc32_fp]) {
449                 be_emit_cstring("\tfmr f0, ");
450                 ppc32_emit_source_register(irn, 0);
451                 be_emit_pad_comment();
452                 be_emit_cstring("/* Swap with moves */\n");
453                 be_emit_write_line();
454
455                 be_emit_cstring("\tfmr ");
456                 ppc32_emit_source_register(irn, 0);
457                 be_emit_cstring(", ");
458                 ppc32_emit_source_register(irn, 1);
459                 be_emit_pad_comment();
460                 be_emit_cstring("/* (continued) */\n");
461                 be_emit_write_line();
462
463                 be_emit_cstring("\tfmr ");
464                 ppc32_emit_source_register(irn, 1);
465                 be_emit_cstring(", f0");
466         } else if (regclass == &ppc32_reg_classes[CLASS_ppc32_condition]) {
467                 be_emit_cstring("\tmcrf cr7, ");
468                 ppc32_emit_source_register(irn, 0);
469                 be_emit_pad_comment();
470                 be_emit_cstring("/* Swap with moves */\n");
471                 be_emit_write_line();
472
473                 be_emit_cstring("\tmcrf ");
474                 ppc32_emit_source_register(irn, 0);
475                 be_emit_cstring(", ");
476                 ppc32_emit_source_register(irn, 1);
477                 be_emit_pad_comment();
478                 be_emit_cstring("/* (continued) */\n");
479                 be_emit_write_line();
480
481                 be_emit_cstring("\tmcrf ");
482                 ppc32_emit_source_register(irn, 1);
483                 be_emit_cstring(", cr7");
484         } else {
485                 panic("ppc32 Emitter: Illegal register class for Perm");
486         }
487         be_emit_finish_line_gas(irn);
488 }
489
490
491 /**
492  * Emits code for a proj -> node
493  */
494 static void emit_Proj(const ir_node *irn)
495 {
496         ir_node *pred = get_Proj_pred(irn);
497
498         if (is_Start(pred)) {
499                 if (get_Proj_proj(irn) == pn_Start_X_initial_exec) {
500                         emit_Jmp(irn);
501                 }
502         }
503 }
504
505 static void emit_be_IncSP(const ir_node *irn)
506 {
507         int offs = be_get_IncSP_offset(irn);
508
509         be_emit_irprintf("\t/* ignored IncSP with %d */", -offs);
510         be_emit_finish_line_gas(irn);
511
512 //      if (offs) {
513 //              assert(offs<=0x7fff);
514 //              lc_efprintf(ppc32_get_arg_env(), F, "\taddi    %1S, %1S, %d\t\t\t/* %+F (IncSP) */\n", irn, irn,
515 //                      -offs, irn);
516 //      }
517 //      else {
518 //              fprintf(F, "\t\t\t\t\t/* omitted IncSP with 0 */\n");
519 //      }
520 }
521
522 /*static void emit_Spill(const ir_node *irn, ppc32_emit_env_t *emit_env) {
523         ir_node *context = be_get_Spill_context(irn);
524         ir_entity *entity = be_get_spill_entity(irn);
525 }*/
526
527 /***********************************************************************************
528  *                  _          __                                             _
529  *                 (_)        / _|                                           | |
530  *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
531  * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
532  * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
533  * |_| |_| |_|\__,_|_|_| |_| |_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
534  *
535  ***********************************************************************************/
536 /**
537  * The type of a emitter function.
538  */
539 typedef void (emit_func)(const ir_node *irn);
540
541 /**
542  * Set a node emitter. Make it a bit more type safe.
543  */
544 static inline void set_emitter(ir_op *op, emit_func ppc32_emit_node)
545 {
546         op->ops.generic = (op_func)ppc32_emit_node;
547 }
548
549 static void ppc32_register_emitters(void)
550 {
551         /* first clear generic function pointers */
552         clear_irp_opcodes_generic_func();
553
554         /* register generated emitter functions */
555         ppc32_register_spec_emitters();
556
557         set_emitter(op_ppc32_Branch, emit_ppc32_Branch);
558         set_emitter(op_ppc32_LoopCopy, emit_ppc32_LoopCopy);
559         set_emitter(op_ppc32_Switch, emit_ppc32_Switch);
560         set_emitter(op_be_Call, emit_be_Call);
561         set_emitter(op_Jmp, emit_Jmp);
562         set_emitter(op_Proj, emit_Proj);
563         set_emitter(op_be_IncSP, emit_be_IncSP);
564         set_emitter(op_be_Copy, emit_be_Copy);
565         set_emitter(op_be_Perm, emit_be_Perm);
566 //      set_emitter(op_Spill, emit_Spill);
567 //      set_emitter(op_Reload, emit_Reload);
568 }
569
570 /**
571  * Emits code for a node.
572  */
573 static void ppc32_emit_node(const ir_node *irn)
574 {
575         ir_op *op = get_irn_op(irn);
576
577         if (op->ops.generic) {
578                 emit_func *emit = (emit_func *)op->ops.generic;
579                 (*emit)(irn);
580         } else {
581                 be_emit_cstring("\t/* TODO */");
582                 be_emit_finish_line_gas(irn);
583         }
584 }
585
586
587 /**
588  * Walks over the nodes in a block connected by scheduling edges
589  * and emits code for each node.
590  */
591 static void ppc32_gen_block(const ir_node *block)
592 {
593         ir_node *irn;
594
595         if (! is_Block(block))
596                 return;
597
598         be_gas_emit_block_name(block);
599         be_emit_cstring(":\n");
600         be_emit_write_line();
601         sched_foreach(block, irn) {
602                 ppc32_emit_node(irn);
603         }
604 }
605
606
607 /**
608  * Emits code for function start.
609  */
610 static void ppc32_emit_start(ir_graph *irg)
611 {
612         const char *irg_name  = get_entity_ld_name(get_irg_entity(irg));
613         int         framesize = get_type_size_bytes(get_irg_frame_type(irg));
614
615         if (! strcmp(irg_name, "main")) {                                          // XXX: underscore hack
616                 irg_name = "_main";
617         }
618
619         be_emit_irprintf("\t.text\n\t.globl %s\n\t.align 4\n%s:\n", irg_name, irg_name);
620
621         if (framesize > 24) {
622                 be_emit_cstring("\tmflr    r0\n");
623                 be_emit_cstring("\tstw     r0, 8(r1)\n");
624                 be_emit_irprintf("\tstwu    r1, -%i(r1)\n", framesize);
625         } else {
626                 be_emit_irprintf("\t/* set new frame (%d) omitted */\n", framesize);
627         }
628         be_emit_write_line();
629
630 /*      if (!isleaf) {
631                 // store link register in linkage area (TODO: if needed)
632
633                 be_emit_cstring("\tmflr    r0\n");
634                 be_emit_cstring("\tstwu    r0, -4(r1)\n");   // stw r0, 8(SP)
635                 be_emit_write_line();
636         }*/
637 }
638
639 /**
640  * Emits code for function end
641  */
642 static void ppc32_emit_end(ir_graph *irg)
643 {
644         int framesize = get_type_size_bytes(get_irg_frame_type(irg));
645         (void) irg;
646
647 /*      if (!isleaf) {
648                 // restore link register
649
650                 be_emit_cstring("\tlwz     r0, 0(r1)\n");
651                 be_emit_cstring("\taddi    r1, r1, 4\n");
652                 be_emit_cstring("\tmtlr    r0\n");
653                 be_emit_write_line();
654         }*/
655         if (framesize > 24) {
656                 be_emit_cstring("\tlwz    r1, 0(r1)\n");
657                 be_emit_cstring("\tlwz    r0, 8(r1)\n");
658                 be_emit_cstring("\tmtlr   r0\n");
659                 be_emit_write_line();
660         }
661         be_emit_cstring("\tblr\n\n");
662         be_emit_write_line();
663 }
664
665 /**
666  * Sets labels for control flow nodes (jump target)
667  * TODO: Jump optimization
668  */
669 static void ppc32_gen_labels(ir_node *block, void *env)
670 {
671         ir_node *pred;
672         int n;
673         (void) env;
674
675         for (n = get_Block_n_cfgpreds(block) - 1; n >= 0; --n) {
676                 pred = get_Block_cfgpred(block, n);
677                 set_irn_link(pred, block);
678         }
679 }
680
681 /**
682  * Main driver: generates code for one routine
683  */
684 void ppc32_gen_routine(const ppc32_code_gen_t *cg, ir_graph *irg)
685 {
686         ir_node *block;
687         int i, n;
688
689         ppc32_register_emitters();
690
691         ppc32_emit_start(irg);
692         irg_block_walk_graph(irg, ppc32_gen_labels, NULL, NULL);
693
694         n = ARR_LEN(cg->blk_sched);
695         for (i = 0; i < n;) {
696                 ir_node *next_bl;
697
698                 block   = cg->blk_sched[i];
699                 ++i;
700                 next_bl = i < n ? cg->blk_sched[i] : NULL;
701
702                 /* set here the link. the emitter expects to find the next block here */
703                 set_irn_link(block, next_bl);
704                 ppc32_gen_block(block);
705         }
706         ppc32_emit_end(irg);
707 }