Set svn:keywords property.
[libfirm] / ir / be / sparc / sparc_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   emit assembler for a backend graph
23  * @version $Id$
24  */
25 #include "config.h"
26
27 #include <limits.h>
28
29 #include "xmalloc.h"
30 #include "tv.h"
31 #include "iredges.h"
32 #include "debug.h"
33 #include "irgwalk.h"
34 #include "irprintf.h"
35 #include "irop_t.h"
36 #include "irargs_t.h"
37 #include "irprog.h"
38 #include "irargs_t.h"
39 #include "error.h"
40 #include "raw_bitset.h"
41 #include "dbginfo.h"
42
43 #include "../besched.h"
44 #include "../beblocksched.h"
45 #include "../beirg.h"
46 #include "../begnuas.h"
47 #include "../be_dbgout.h"
48 #include "../benode.h"
49
50 #include "sparc_emitter.h"
51 #include "gen_sparc_emitter.h"
52 #include "sparc_nodes_attr.h"
53 #include "sparc_new_nodes.h"
54
55 #define SNPRINTF_BUF_LEN 128
56 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
57
58 /**
59  * Returns the register at in position pos.
60  */
61 static const arch_register_t *get_in_reg(const ir_node *node, int pos)
62 {
63         ir_node                *op;
64         const arch_register_t  *reg = NULL;
65
66         assert(get_irn_arity(node) > pos && "Invalid IN position");
67
68         /* The out register of the operator at position pos is the
69            in register we need. */
70         op = get_irn_n(node, pos);
71
72         reg = arch_get_irn_register(op);
73
74         assert(reg && "no in register found");
75         return reg;
76 }
77
78 /**
79  * Returns the register at out position pos.
80  */
81 static const arch_register_t *get_out_reg(const ir_node *node, int pos)
82 {
83         ir_node                *proj;
84         const arch_register_t  *reg = NULL;
85
86         /* 1st case: irn is not of mode_T, so it has only                 */
87         /*           one OUT register -> good                             */
88         /* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
89         /*           Proj with the corresponding projnum for the register */
90
91         if (get_irn_mode(node) != mode_T) {
92                 reg = arch_get_irn_register(node);
93         } else if (is_sparc_irn(node)) {
94                 reg = arch_irn_get_register(node, pos);
95         } else {
96                 const ir_edge_t *edge;
97
98                 foreach_out_edge(node, edge) {
99                         proj = get_edge_src_irn(edge);
100                         assert(is_Proj(proj) && "non-Proj from mode_T node");
101                         if (get_Proj_proj(proj) == pos) {
102                                 reg = arch_get_irn_register(proj);
103                                 break;
104                         }
105                 }
106         }
107
108         assert(reg && "no out register found");
109         return reg;
110 }
111
112 /*************************************************************
113  *             _       _    __   _          _
114  *            (_)     | |  / _| | |        | |
115  *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
116  * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
117  * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
118  * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
119  * | |                                       | |
120  * |_|                                       |_|
121  *************************************************************/
122
123 void sparc_emit_immediate(const ir_node *node)
124 {
125         // TODO: make sure it's a valid simm13 ?
126         const sparc_attr_t *attr = get_sparc_attr_const(node);
127         be_emit_irprintf("%d", attr->immediate_value);
128 }
129
130 void sparc_emit_source_register(const ir_node *node, int pos)
131 {
132         const arch_register_t *reg = get_in_reg(node, pos);
133         be_emit_char('%');
134         be_emit_string(arch_register_get_name(reg));
135 }
136
137 void sparc_emit_dest_register(const ir_node *node, int pos)
138 {
139         const arch_register_t *reg = get_out_reg(node, pos);
140         be_emit_char('%');
141         be_emit_string(arch_register_get_name(reg));
142 }
143
144 /**
145  * Emits either a imm or register depending on arity of node
146  * @param node
147  * @param register no (-1 if no register)
148  */
149 void sparc_emit_reg_or_imm(const ir_node *node, int pos)
150 {
151         if (get_irn_arity(node) > pos) {
152                 // we have reg input
153                 sparc_emit_source_register(node, pos);
154         } else {
155                 // we have a imm input
156                 sparc_emit_immediate(node);
157         }
158 }
159
160 /**
161  * emit SP offset
162  */
163 void sparc_emit_offset(const ir_node *node)
164 {
165         const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
166         assert(attr->base.is_load_store);
167         if (attr->offset > 0)
168                 be_emit_irprintf("+0x%X", attr->offset);
169 }
170
171 /**
172  *  Emit load mode char
173  */
174 void sparc_emit_load_mode(const ir_node *node)
175 {
176         const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
177     ir_mode *mode      = attr->load_store_mode;
178     int      bits      = get_mode_size_bits(mode);
179     bool     is_signed = mode_is_signed(mode);
180
181     if (bits == 16) {
182         be_emit_string(is_signed ? "sh" : "uh");
183     } else if (bits == 8) {
184         be_emit_string(is_signed ? "sb" : "ub");
185     } else if (bits == 64) {
186         be_emit_string("d");
187     } else {
188         assert(bits == 32);
189     }
190 }
191
192 /**
193  * Emit store mode char
194  */
195 void sparc_emit_store_mode(const ir_node *node)
196 {
197         const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
198     ir_mode *mode      = attr->load_store_mode;
199     int      bits      = get_mode_size_bits(mode);
200
201     if (bits == 16) {
202         be_emit_string("h");
203     } else if (bits == 8) {
204         be_emit_string("b");
205     } else if (bits == 64) {
206         be_emit_string("d");
207     } else {
208         assert(bits == 32);
209     }
210 }
211
212 /**
213  * Returns the target label for a control flow node.
214  */
215 static void sparc_emit_cfop_target(const ir_node *node)
216 {
217         ir_node *block = get_irn_link(node);
218         be_gas_emit_block_name(block);
219 }
220
221 /**
222  * Emit single entity
223  */
224 static void sparc_emit_entity(ir_entity *entity)
225 {
226         be_emit_ident(get_entity_ld_ident(entity));
227 }
228
229 /***********************************************************************************
230  *                  _          __                                             _
231  *                 (_)        / _|                                           | |
232  *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
233  * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
234  * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
235  * |_| |_| |_|\__,_|_|_| |_| |_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
236  *
237  ***********************************************************************************/
238
239
240 /**
241  * Emits code for stack space management
242  */
243 static void emit_be_IncSP(const ir_node *irn)
244 {
245         int offs = -be_get_IncSP_offset(irn);
246
247         if (offs != 0) {
248                 /* SPARC stack grows downwards */
249                 if (offs < 0) {
250                         be_emit_cstring("\tsub ");
251                         offs = -offs;
252                 } else {
253                         be_emit_cstring("\tadd ");
254                 }
255
256                 sparc_emit_source_register(irn, 0);
257                 be_emit_irprintf(", %d", offs);
258                 be_emit_cstring(", ");
259                 sparc_emit_dest_register(irn, 0);
260                 be_emit_finish_line_gas(irn);
261         } else {
262                 // ignore IncSP(0)
263                 //be_emit_cstring("\t/* IncSP(0) skipped */");
264
265 //              be_emit_cstring("\t/* ");
266 //              be_emit_cstring("sub ");
267 //              offs = -offs;
268 //              sparc_emit_source_register(irn, 0);
269 //              be_emit_irprintf(", %d", offs);
270 //              be_emit_cstring(", ");
271 //              sparc_emit_dest_register(irn, 0);
272 //              be_emit_cstring(" ignored */ ");
273 //              be_emit_finish_line_gas(irn);
274         }
275
276
277 }
278
279 /**
280  * Emits code for return node
281  */
282 static void emit_be_Return(const ir_node *irn)
283 {
284         be_emit_cstring("\tret");
285         be_emit_finish_line_gas(irn);
286 }
287
288 /**
289  * Emits code for Call node
290  */
291 static void emit_be_Call(const ir_node *irn)
292 {
293         ir_entity *entity = be_Call_get_entity(irn);
294
295         if (entity != NULL) {
296                 be_emit_cstring("\tcall ");
297             sparc_emit_entity(entity);
298                 be_emit_finish_line_gas(irn);
299                 be_emit_cstring("\tnop");
300                 be_emit_pad_comment();
301                 be_emit_cstring("/* TODO: use delay slot */\n");
302         } else {
303                 be_emit_cstring("\tnop\n");
304                 be_emit_pad_comment();
305                 be_emit_cstring("/* TODO: Entity == NULL */\n");
306                 be_emit_finish_line_gas(irn);
307         }
308 }
309
310 /**
311  * Emit a SymConst.
312  */
313 static void emit_sparc_SymConst(const ir_node *irn)
314 {
315         const sparc_symconst_attr_t *attr = get_sparc_symconst_attr_const(irn);
316         //const char *entity_name = get_entity_ld_name(attr->entity);
317         ident *id_symconst = get_entity_ident(attr->entity);
318         const char *label = get_id_str(id_symconst);
319
320         //sethi %hi(const32),%reg
321         //or    %reg,%lo(const32),%reg
322
323         be_emit_irprintf("\tsethi %%hi(%s), ", label);
324         sparc_emit_dest_register(irn, 0);
325         be_emit_cstring("\n ");
326         be_emit_cstring("\tor ");
327         sparc_emit_dest_register(irn, 0);
328         be_emit_irprintf(", %%lo(%s), ", label);
329         sparc_emit_dest_register(irn, 0);
330         be_emit_finish_line_gas(irn);
331 }
332
333
334 /**
335  * Emits code for FrameAddr fix
336  */
337 static void emit_sparc_FrameAddr(const ir_node *irn)
338 {
339         const sparc_symconst_attr_t *attr = get_irn_generic_attr_const(irn);
340         be_emit_cstring("\tadd ");
341         sparc_emit_source_register(irn, 0);
342         be_emit_cstring(", ");
343         be_emit_irprintf("0x%X", attr->fp_offset);
344         be_emit_cstring(", ");
345         sparc_emit_dest_register(irn, 0);
346         be_emit_finish_line_gas(irn);
347 }
348
349
350 /**
351  * Emits code for Branch
352  */
353 static void emit_sparc_Branch(const ir_node *irn)
354 {
355         const ir_edge_t *edge;
356         const ir_node *proj_true  = NULL;
357         const ir_node *proj_false = NULL;
358         const ir_node *block;
359         const ir_node *next_block;
360         ir_node *op1 = get_irn_n(irn, 0);
361         const char *suffix;
362         int proj_num = get_sparc_jmp_cond_proj_num(irn);
363         const sparc_cmp_attr_t *cmp_attr = get_irn_generic_attr_const(op1);
364         // bool is_signed = !cmp_attr->is_unsigned;
365
366         assert(is_sparc_Cmp(op1) || is_sparc_Tst(op1));
367
368         foreach_out_edge(irn, edge) {
369                 ir_node *proj = get_edge_src_irn(edge);
370                 long nr = get_Proj_proj(proj);
371                 if (nr == pn_Cond_true) {
372                         proj_true = proj;
373                 } else {
374                         proj_false = proj;
375                 }
376         }
377
378         if (cmp_attr->ins_permuted) {
379                 proj_num = get_mirrored_pnc(proj_num);
380         }
381
382         /* for now, the code works for scheduled and non-schedules blocks */
383         block = get_nodes_block(irn);
384
385         /* we have a block schedule */
386         next_block = get_irn_link(block);
387
388         assert(proj_num != pn_Cmp_False);
389         assert(proj_num != pn_Cmp_True);
390
391         if (get_irn_link(proj_true) == next_block) {
392                 /* exchange both proj's so the second one can be omitted */
393                 const ir_node *t = proj_true;
394
395                 proj_true  = proj_false;
396                 proj_false = t;
397                 proj_num   = get_negated_pnc(proj_num, mode_Iu);
398         }
399
400         switch (proj_num) {
401                 case pn_Cmp_Eq:  suffix = "e"; break;
402                 case pn_Cmp_Lt:  suffix = "l"; break;
403                 case pn_Cmp_Le:  suffix = "le"; break;
404                 case pn_Cmp_Gt:  suffix = "g"; break;
405                 case pn_Cmp_Ge:  suffix = "ge"; break;
406                 case pn_Cmp_Lg:  suffix = "ne"; break;
407                 case pn_Cmp_Leg: suffix = "a"; break;
408                 default: panic("Cmp has unsupported pnc");
409         }
410
411         /* emit the true proj */
412         be_emit_irprintf("\tb%s ", suffix);
413         sparc_emit_cfop_target(proj_true);
414         be_emit_finish_line_gas(proj_true);
415
416         be_emit_cstring("\tnop");
417         be_emit_pad_comment();
418         be_emit_cstring("/* TODO: use delay slot */\n");
419
420         if (get_irn_link(proj_false) == next_block) {
421                 be_emit_cstring("\t/* false-fallthrough to ");
422                 sparc_emit_cfop_target(proj_false);
423                 be_emit_cstring(" */");
424                 be_emit_finish_line_gas(proj_false);
425         } else {
426                 be_emit_cstring("\tba ");
427                 sparc_emit_cfop_target(proj_false);
428                 be_emit_finish_line_gas(proj_false);
429                 be_emit_cstring("\tnop\t\t/* TODO: use delay slot */");
430                 be_emit_write_line();
431         }
432 }
433
434 /**
435  * emit Jmp (which actually is a branch always)
436  */
437 static void emit_sparc_Jmp(const ir_node *node)
438 {
439         ir_node *block, *next_block;
440
441         /* for now, the code works for scheduled and non-schedules blocks */
442         block = get_nodes_block(node);
443
444         /* we have a block schedule */
445         next_block = get_irn_link(block);
446         if (get_irn_link(node) != next_block) {
447                 be_emit_cstring("\tba ");
448                 sparc_emit_cfop_target(node);
449         } else {
450                 be_emit_cstring("\t/* fallthrough to ");
451                 sparc_emit_cfop_target(node);
452                 be_emit_cstring(" */");
453         }
454         be_emit_finish_line_gas(node);
455 }
456
457 static void emit_be_Copy(const ir_node *irn)
458 {
459         ir_mode *mode = get_irn_mode(irn);
460
461         if (get_in_reg(irn, 0) == get_out_reg(irn, 0)) {
462                 /* omitted Copy */
463                 return;
464         }
465
466         if (mode_is_float(mode)) {
467                 panic("emit_be_Copy: move not supported for FP");
468         } else if (mode_is_data(mode)) {
469                 be_emit_cstring("\tmov ");
470                 sparc_emit_source_register(irn, 0);
471                 be_emit_cstring(", ");
472                 sparc_emit_dest_register(irn, 0);
473                 be_emit_finish_line_gas(irn);
474         } else {
475                 panic("emit_be_Copy: move not supported for this mode");
476         }
477 }
478
479
480 /**
481  * dummy emitter for ignored nodes
482  */
483 static void emit_nothing(const ir_node *irn)
484 {
485         (void) irn;
486 }
487
488
489
490 /**
491  * type of emitter function
492  */
493 typedef void (*emit_func) (const ir_node *);
494
495 /**
496  * Set a node emitter. Make it a bit more type safe.
497  */
498 static inline void set_emitter(ir_op *op, emit_func sparc_emit_node)
499 {
500         op->ops.generic = (op_func)sparc_emit_node;
501 }
502
503 /**
504  * Enters the emitter functions for handled nodes into the generic
505  * pointer of an opcode.
506  */
507 static void sparc_register_emitters(void)
508 {
509
510         /* first clear the generic function pointer for all ops */
511         clear_irp_opcodes_generic_func();
512
513         /* register all emitter functions defined in spec */
514         sparc_register_spec_emitters();
515
516         /* custom emitter */
517     set_emitter(op_be_IncSP,       emit_be_IncSP);
518     set_emitter(op_be_Return,      emit_be_Return);
519     set_emitter(op_be_Call,        emit_be_Call);
520     set_emitter(op_sparc_FrameAddr,  emit_sparc_FrameAddr);
521     set_emitter(op_sparc_Branch,   emit_sparc_Branch);
522     set_emitter(op_sparc_SymConst,   emit_sparc_SymConst);
523     set_emitter(op_sparc_Jmp,        emit_sparc_Jmp);
524
525     set_emitter(op_be_Copy,        emit_be_Copy);
526     set_emitter(op_be_CopyKeep,    emit_be_Copy);
527
528 /*
529     set_emitter(op_arm_B,          emit_arm_B);
530     set_emitter(op_arm_CopyB,      emit_arm_CopyB);
531     set_emitter(op_arm_fpaConst,   emit_arm_fpaConst);
532     set_emitter(op_arm_fpaDbl2GP,  emit_arm_fpaDbl2GP);
533     set_emitter(op_arm_LdTls,      emit_arm_LdTls);
534     set_emitter(op_arm_SwitchJmp,  emit_arm_SwitchJmp);
535     set_emitter(op_be_MemPerm,     emit_be_MemPerm);
536     set_emitter(op_be_Perm,        emit_be_Perm);
537 */
538     /* no need to emit anything for the following nodes */
539         set_emitter(op_Phi,            emit_nothing);
540         set_emitter(op_be_Keep,        emit_nothing);
541         set_emitter(op_be_Start,       emit_nothing);
542         set_emitter(op_be_Barrier,     emit_nothing);
543
544 }
545
546 /**
547  * Emits code for a node.
548  */
549 static void sparc_emit_node(const ir_node *node)
550 {
551         ir_op               *op       = get_irn_op(node);
552
553         if (op->ops.generic) {
554                 emit_func func = (emit_func) op->ops.generic;
555                 be_dbg_set_dbg_info(get_irn_dbg_info(node));
556                 (*func) (node);
557         } else {
558                 panic("Error: No emit handler for node %+F (graph %+F)\n",
559                         node, current_ir_graph);
560         }
561 }
562
563 /**
564  * Walks over the nodes in a block connected by scheduling edges
565  * and emits code for each node.
566  */
567 static void sparc_gen_block(ir_node *block, void *data)
568 {
569         ir_node *node;
570         (void) data;
571
572         if (! is_Block(block))
573                 return;
574
575         be_gas_emit_block_name(block);
576         be_emit_cstring(":\n");
577         be_emit_write_line();
578
579         sched_foreach(block, node) {
580                 sparc_emit_node(node);
581         }
582 }
583
584
585 /**
586  * Emits code for function start.
587  */
588 static void sparc_emit_func_prolog(ir_graph *irg)
589 {
590         ir_entity *ent = get_irg_entity(irg);
591
592         be_gas_emit_function_prolog(ent, 4);
593         // TODO: fetch reg names via API func
594         // TODO: move value to SPARC_MIN_STACKSIZE const
595         be_emit_cstring("\tsave %sp, -64, %sp");
596         be_emit_cstring("\t/* incr CWP and alloc min. required stack space */\n");
597         be_emit_write_line();
598 }
599
600 /**
601  * Emits code for function end
602  */
603 static void sparc_emit_func_epilog(ir_graph *irg)
604 {
605         ir_entity *ent = get_irg_entity(irg);
606         const char *irg_name = get_entity_ld_name(ent);
607
608         be_emit_cstring("\trestore");
609         be_emit_cstring("\t/* decr CWP */\n");
610         be_emit_irprintf("\t.size  %s, .-%s\n", irg_name, irg_name);
611         be_emit_cstring("# -- End ");
612         be_emit_string(irg_name);
613         be_emit_cstring("\n");
614         be_emit_write_line();
615 }
616
617 /**
618  * Block-walker:
619  * TODO: Sets labels for control flow nodes (jump target).
620  * Links control predecessors to there destination blocks.
621  */
622 static void sparc_gen_labels(ir_node *block, void *env)
623 {
624         ir_node *pred;
625         int n = get_Block_n_cfgpreds(block);
626         (void) env;
627
628         for (n--; n >= 0; n--) {
629                 pred = get_Block_cfgpred(block, n);
630                 set_irn_link(pred, block); // link the pred of a block (which is a jmp)
631         }
632 }
633
634
635 /**
636  * Main driver
637  */
638 void sparc_gen_routine(const sparc_code_gen_t *cg, ir_graph *irg)
639 {
640         ir_node **blk_sched;
641         ir_node *last_block = NULL;
642         ir_entity *entity     = get_irg_entity(irg);
643         int i, n;
644
645         be_gas_elf_type_char = '#';
646
647         /* register all emitter functions */
648         sparc_register_emitters();
649         be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi));
650
651         /* create the block schedule. For now, we don't need it earlier. */
652         blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq);
653
654         // emit function prolog
655         sparc_emit_func_prolog(irg);
656
657         // generate BLOCK labels
658         irg_block_walk_graph(irg, sparc_gen_labels, NULL, NULL);
659
660         // inject block scheduling links & emit code of each block
661         n = ARR_LEN(blk_sched);
662         for (i = 0; i < n;) {
663                 ir_node *block, *next_bl;
664
665                 block = blk_sched[i];
666                 ++i;
667                 next_bl = i < n ? blk_sched[i] : NULL;
668
669                 /* set here the link. the emitter expects to find the next block here */
670                 set_irn_link(block, next_bl);
671                 sparc_gen_block(block, last_block);
672                 last_block = block;
673         }
674
675
676         //irg_walk_blkwise_graph(irg, NULL, sparc_gen_block, NULL);
677
678         // emit function epilog
679         sparc_emit_func_epilog(irg);
680 }
681
682 void sparc_init_emitter(void)
683 {
684         FIRM_DBG_REGISTER(dbg, "firm.be.sparc.emit");
685 }