04ed07a4f68c4a996ae4af0f284d6f3cd465ef27
[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: sparc_emitter.c 26542 2009-09-18 09:18:32Z matze $
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_emit_irprintf("BLOCK_%ld", get_irn_node_nr(block));
219 }
220
221 /**
222  * Emit single entity
223  */
224 static void sparc_emit_entity(ir_entity *entity)
225 {
226         set_entity_backend_marked(entity, 1);
227         be_emit_ident(get_entity_ld_ident(entity));
228 }
229
230 /***********************************************************************************
231  *                  _          __                                             _
232  *                 (_)        / _|                                           | |
233  *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
234  * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
235  * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
236  * |_| |_| |_|\__,_|_|_| |_| |_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
237  *
238  ***********************************************************************************/
239
240
241 /**
242  * Emits code for stack space management
243  */
244 static void emit_be_IncSP(const ir_node *irn)
245 {
246         int offs = -be_get_IncSP_offset(irn);
247
248         if (offs != 0) {
249                 /* SPARC stack grows downwards */
250                 if (offs < 0) {
251                         be_emit_cstring("\tsub ");
252                         offs = -offs;
253                 } else {
254                         be_emit_cstring("\tadd ");
255                 }
256
257                 sparc_emit_source_register(irn, 0);
258                 be_emit_irprintf(", %d", offs);
259                 be_emit_cstring(", ");
260                 sparc_emit_dest_register(irn, 0);
261                 be_emit_finish_line_gas(irn);
262         } else {
263                 // ignore IncSP(0)
264                 //be_emit_cstring("\t/* IncSP(0) skipped */");
265
266 //              be_emit_cstring("\t/* ");
267 //              be_emit_cstring("sub ");
268 //              offs = -offs;
269 //              sparc_emit_source_register(irn, 0);
270 //              be_emit_irprintf(", %d", offs);
271 //              be_emit_cstring(", ");
272 //              sparc_emit_dest_register(irn, 0);
273 //              be_emit_cstring(" ignored */ ");
274 //              be_emit_finish_line_gas(irn);
275         }
276
277
278 }
279
280 /**
281  * Emits code for return node
282  */
283 static void emit_be_Return(const ir_node *irn)
284 {
285         be_emit_cstring("\tret");
286         be_emit_finish_line_gas(irn);
287 }
288
289 /**
290  * Emits code for Call node
291  */
292 static void emit_be_Call(const ir_node *irn)
293 {
294         ir_entity *entity = be_Call_get_entity(irn);
295
296         if (entity != NULL) {
297                 be_emit_cstring("\tcall ");
298             sparc_emit_entity(entity);
299                 be_emit_finish_line_gas(irn);
300                 be_emit_cstring("\tnop");
301                 be_emit_pad_comment();
302                 be_emit_cstring("/* TODO: use delay slot */\n");
303         } else {
304                 be_emit_cstring("\tnop\n");
305                 be_emit_pad_comment();
306                 be_emit_cstring("/* TODO: Entity == NULL */\n");
307                 be_emit_finish_line_gas(irn);
308         }
309 }
310
311 /**
312  * Emit a SymConst.
313  */
314 static void emit_sparc_SymConst(const ir_node *irn)
315 {
316         const sparc_symconst_attr_t *attr = get_sparc_symconst_attr_const(irn);
317         //const char *entity_name = get_entity_ld_name(attr->entity);
318         ident *id_symconst = get_entity_ident(attr->entity);
319         const char *label = get_id_str(id_symconst);
320
321         //sethi %hi(const32),%reg
322         //or    %reg,%lo(const32),%reg
323
324         be_emit_irprintf("\tsethi %%hi(%s), ", label);
325         sparc_emit_dest_register(irn, 0);
326         be_emit_cstring("\n ");
327         be_emit_cstring("\tor ");
328         sparc_emit_dest_register(irn, 0);
329         be_emit_irprintf(", %%lo(%s), ", label);
330         sparc_emit_dest_register(irn, 0);
331         be_emit_finish_line_gas(irn);
332 }
333
334
335 /**
336  * Emits code for FrameAddr fix
337  */
338 static void emit_sparc_FrameAddr(const ir_node *irn)
339 {
340         const sparc_symconst_attr_t *attr = get_irn_generic_attr_const(irn);
341         be_emit_cstring("\tadd ");
342         sparc_emit_source_register(irn, 0);
343         be_emit_cstring(", ");
344         be_emit_irprintf("0x%X", attr->fp_offset);
345         be_emit_cstring(", ");
346         sparc_emit_dest_register(irn, 0);
347         be_emit_finish_line_gas(irn);
348 }
349
350
351 /**
352  * Emits code for Branch
353  */
354 static void emit_sparc_Branch(const ir_node *irn)
355 {
356         const ir_edge_t *edge;
357         const ir_node *proj_true  = NULL;
358         const ir_node *proj_false = NULL;
359         const ir_node *block;
360         const ir_node *next_block;
361         ir_node *op1 = get_irn_n(irn, 0);
362         const char *suffix;
363         int proj_num = get_sparc_jmp_cond_proj_num(irn);
364         const sparc_cmp_attr_t *cmp_attr = get_irn_generic_attr_const(op1);
365         // bool is_signed = !cmp_attr->is_unsigned;
366
367         assert(is_sparc_Cmp(op1) || is_sparc_Tst(op1));
368
369         foreach_out_edge(irn, edge) {
370                 ir_node *proj = get_edge_src_irn(edge);
371                 long nr = get_Proj_proj(proj);
372                 if (nr == pn_Cond_true) {
373                         proj_true = proj;
374                 } else {
375                         proj_false = proj;
376                 }
377         }
378
379         if (cmp_attr->ins_permuted) {
380                 proj_num = get_mirrored_pnc(proj_num);
381         }
382
383         /* for now, the code works for scheduled and non-schedules blocks */
384         block = get_nodes_block(irn);
385
386         /* we have a block schedule */
387         next_block = get_irn_link(block);
388
389         assert(proj_num != pn_Cmp_False);
390         assert(proj_num != pn_Cmp_True);
391
392         if (get_irn_link(proj_true) == next_block) {
393                 /* exchange both proj's so the second one can be omitted */
394                 const ir_node *t = proj_true;
395
396                 proj_true  = proj_false;
397                 proj_false = t;
398                 proj_num   = get_negated_pnc(proj_num, mode_Iu);
399         }
400
401         switch (proj_num) {
402                 case pn_Cmp_Eq:  suffix = "e"; break;
403                 case pn_Cmp_Lt:  suffix = "l"; break;
404                 case pn_Cmp_Le:  suffix = "le"; break;
405                 case pn_Cmp_Gt:  suffix = "g"; break;
406                 case pn_Cmp_Ge:  suffix = "ge"; break;
407                 case pn_Cmp_Lg:  suffix = "ne"; break;
408                 case pn_Cmp_Leg: suffix = "a"; break;
409                 default: panic("Cmp has unsupported pnc");
410         }
411
412         /* emit the true proj */
413         be_emit_irprintf("\tb%s ", suffix);
414         sparc_emit_cfop_target(proj_true);
415         be_emit_finish_line_gas(proj_true);
416
417         be_emit_cstring("\tnop");
418         be_emit_pad_comment();
419         be_emit_cstring("/* TODO: use delay slot */\n");
420
421         if (get_irn_link(proj_false) == next_block) {
422                 be_emit_cstring("\t/* false-fallthrough to ");
423                 sparc_emit_cfop_target(proj_false);
424                 be_emit_cstring(" */");
425                 be_emit_finish_line_gas(proj_false);
426         } else {
427                 be_emit_cstring("\tba ");
428                 sparc_emit_cfop_target(proj_false);
429                 be_emit_finish_line_gas(proj_false);
430                 be_emit_cstring("\tnop\t\t/* TODO: use delay slot */");
431                 be_emit_write_line();
432         }
433 }
434
435 /**
436  * emit Jmp (which actually is a branch always)
437  */
438 static void emit_sparc_Jmp(const ir_node *node)
439 {
440         ir_node *block, *next_block;
441
442         /* for now, the code works for scheduled and non-schedules blocks */
443         block = get_nodes_block(node);
444
445         /* we have a block schedule */
446         next_block = get_irn_link(block);
447         if (get_irn_link(node) != next_block) {
448                 be_emit_cstring("\tba ");
449                 sparc_emit_cfop_target(node);
450         } else {
451                 be_emit_cstring("\t/* fallthrough to ");
452                 sparc_emit_cfop_target(node);
453                 be_emit_cstring(" */");
454         }
455         be_emit_finish_line_gas(node);
456 }
457
458 static void emit_be_Copy(const ir_node *irn) {
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                 assert(0 && "move not supported for this mode");
476                 panic("emit_be_Copy: move not supported for this mode");
477         }
478 }
479
480
481 /**
482  * dummy emitter for ignored nodes
483  */
484 static void emit_nothing(const ir_node *irn)
485 {
486         (void) irn;
487 }
488
489
490
491 /**
492  * type of emitter function
493  */
494 typedef void (*emit_func) (const ir_node *);
495
496 /**
497  * Set a node emitter. Make it a bit more type safe.
498  */
499 static inline void set_emitter(ir_op *op, emit_func sparc_emit_node)
500 {
501         op->ops.generic = (op_func)sparc_emit_node;
502 }
503
504 /**
505  * Enters the emitter functions for handled nodes into the generic
506  * pointer of an opcode.
507  */
508 static void sparc_register_emitters(void)
509 {
510
511         /* first clear the generic function pointer for all ops */
512         clear_irp_opcodes_generic_func();
513
514         /* register all emitter functions defined in spec */
515         sparc_register_spec_emitters();
516
517         /* custom emitter */
518     set_emitter(op_be_IncSP,       emit_be_IncSP);
519     set_emitter(op_be_Return,      emit_be_Return);
520     set_emitter(op_be_Call,        emit_be_Call);
521     set_emitter(op_sparc_FrameAddr,  emit_sparc_FrameAddr);
522     set_emitter(op_sparc_Branch,   emit_sparc_Branch);
523     set_emitter(op_sparc_SymConst,   emit_sparc_SymConst);
524     set_emitter(op_sparc_Jmp,        emit_sparc_Jmp);
525
526     set_emitter(op_be_Copy,        emit_be_Copy);
527     set_emitter(op_be_CopyKeep,    emit_be_Copy);
528
529 /*
530     set_emitter(op_arm_B,          emit_arm_B);
531     set_emitter(op_arm_CopyB,      emit_arm_CopyB);
532     set_emitter(op_arm_fpaConst,   emit_arm_fpaConst);
533     set_emitter(op_arm_fpaDbl2GP,  emit_arm_fpaDbl2GP);
534     set_emitter(op_arm_LdTls,      emit_arm_LdTls);
535     set_emitter(op_arm_SwitchJmp,  emit_arm_SwitchJmp);
536     set_emitter(op_be_MemPerm,     emit_be_MemPerm);
537     set_emitter(op_be_Perm,        emit_be_Perm);
538 */
539     /* no need to emit anything for the following nodes */
540         set_emitter(op_Phi,            emit_nothing);
541         set_emitter(op_be_Keep,        emit_nothing);
542         set_emitter(op_be_Start,       emit_nothing);
543         set_emitter(op_be_Barrier,     emit_nothing);
544
545 }
546
547 /**
548  * Emits code for a node.
549  */
550 void sparc_emit_node(const ir_node *node)
551 {
552         ir_op               *op       = get_irn_op(node);
553
554         if (op->ops.generic) {
555                 emit_func func = (emit_func) op->ops.generic;
556                 be_dbg_set_dbg_info(get_irn_dbg_info(node));
557                 (*func) (node);
558         } else {
559                 panic("Error: No emit handler for node %+F (graph %+F)\n",
560                         node, current_ir_graph);
561         }
562 }
563
564 /**
565  * Walks over the nodes in a block connected by scheduling edges
566  * and emits code for each node.
567  */
568 void sparc_gen_block(ir_node *block, void *data) {
569         ir_node *node;
570         (void) data;
571
572         if (! is_Block(block))
573                 return;
574         be_emit_cstring("BLOCK_");
575         be_emit_irprintf("%ld:\n", get_irn_node_nr(block));
576         be_emit_write_line();
577
578         sched_foreach(block, node) {
579                 sparc_emit_node(node);
580         }
581 }
582
583
584 /**
585  * Emits code for function start.
586  */
587 void sparc_emit_func_prolog(ir_graph *irg) {
588         ir_entity *ent = get_irg_entity(irg);
589
590         be_gas_emit_function_prolog(ent, 4);
591         // TODO: fetch reg names via API func
592         // TODO: move value to SPARC_MIN_STACKSIZE const
593         be_emit_cstring("\tsave %sp, -64, %sp");
594         be_emit_cstring("\t/* incr CWP and alloc min. required stack space */\n");
595         be_emit_write_line();
596 }
597
598 /**
599  * Emits code for function end
600  */
601 void sparc_emit_func_epilog(ir_graph *irg) {
602         ir_entity *ent = get_irg_entity(irg);
603         const char *irg_name = get_entity_ld_name(ent);
604
605         be_emit_cstring("\trestore");
606         be_emit_cstring("\t/* decr CWP */\n");
607         be_emit_irprintf("\t.size  %s, .-%s\n", irg_name, irg_name);
608         be_emit_cstring("# -- End ");
609         be_emit_string(irg_name);
610         be_emit_cstring("\n");
611         be_emit_write_line();
612 }
613
614 /**
615  * Block-walker:
616  * TODO: Sets labels for control flow nodes (jump target).
617  * Links control predecessors to there destination blocks.
618  */
619 void sparc_gen_labels(ir_node *block, void *env) {
620         ir_node *pred;
621         int n = get_Block_n_cfgpreds(block);
622         (void) env;
623
624         for (n--; n >= 0; n--) {
625                 pred = get_Block_cfgpred(block, n);
626                 set_irn_link(pred, block); // link the pred of a block (which is a jmp)
627         }
628 }
629
630
631 /**
632  * Main driver
633  */
634 void sparc_gen_routine(const sparc_code_gen_t *cg, ir_graph *irg)
635 {
636         ir_node **blk_sched;
637         ir_node *last_block = NULL;
638         ir_entity *entity     = get_irg_entity(irg);
639         int i, n;
640
641         be_gas_elf_type_char = '#';
642
643         /* register all emitter functions */
644         sparc_register_emitters();
645         be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi));
646
647         /* create the block schedule. For now, we don't need it earlier. */
648         blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq);
649
650         // emit function prolog
651         sparc_emit_func_prolog(irg);
652
653         // generate BLOCK labels
654         irg_block_walk_graph(irg, sparc_gen_labels, NULL, NULL);
655
656         // inject block scheduling links & emit code of each block
657         n = ARR_LEN(blk_sched);
658         for (i = 0; i < n;) {
659                 ir_node *block, *next_bl;
660
661                 block = blk_sched[i];
662                 ++i;
663                 next_bl = i < n ? blk_sched[i] : NULL;
664
665                 /* set here the link. the emitter expects to find the next block here */
666                 set_irn_link(block, next_bl);
667                 sparc_gen_block(block, last_block);
668                 last_block = block;
669         }
670
671
672         //irg_walk_blkwise_graph(irg, NULL, sparc_gen_block, NULL);
673
674         // emit function epilog
675         sparc_emit_func_epilog(irg);
676 }
677
678 void sparc_init_emitter(void)
679 {
680         FIRM_DBG_REGISTER(dbg, "firm.be.sparc.emit");
681 }