dce4963c9014b3265e7d11c867c7b19927e4667e
[libfirm] / ir / be / ppc32 / ppc32_new_nodes.c
1 /**
2  * This file implements the creation of the achitecture specific firm opcodes
3  * and the coresponding node constructors for the ppc assembler irg.
4  * $Id$
5  */
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #ifdef _WIN32
11 #include <malloc.h>
12 #else
13 #include <alloca.h>
14 #endif
15
16 #include <stdlib.h>
17
18 #include "irprog_t.h"
19 #include "irgraph_t.h"
20 #include "irnode_t.h"
21 #include "irmode_t.h"
22 #include "ircons_t.h"
23 #include "iropt_t.h"
24 #include "irop.h"
25 #include "firm_common_t.h"
26 #include "irvrfy_t.h"
27 #include "irprintf.h"
28
29 #include "../bearch.h"
30
31 #include "ppc32_nodes_attr.h"
32 #include "ppc32_new_nodes.h"
33 #include "gen_ppc32_regalloc_if.h"
34
35
36
37 /***********************************************************************************
38  *      _                                   _       _             __
39  *     | |                                 (_)     | |           / _|
40  *   __| |_   _ _ __ ___  _ __   ___ _ __   _ _ __ | |_ ___ _ __| |_ __ _  ___ ___
41  *  / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__|  _/ _` |/ __/ _ \
42  * | (_| | |_| | | | | | | |_) |  __/ |    | | | | | ||  __/ |  | || (_| | (_|  __/
43  *  \__,_|\__,_|_| |_| |_| .__/ \___|_|    |_|_| |_|\__\___|_|  |_| \__,_|\___\___|
44  *                       | |
45  *                       |_|
46  ***********************************************************************************/
47
48 /**
49  * Returns a string containing the names of all registers within the limited bitset
50  */
51 static char *get_limited_regs(const arch_register_req_t *req, char *buf, int max) {
52         bitset_t *bs   = bitset_alloca(req->cls->n_regs);
53         char     *p    = buf;
54         int       size = 0;
55         int       i, cnt;
56
57         req->limited(NULL, bs);
58
59         for (i = 0; i < req->cls->n_regs; i++) {
60                 if (bitset_is_set(bs, i)) {
61                         cnt = snprintf(p, max - size, " %s", req->cls->regs[i].name);
62                         if (cnt < 0) {
63                                 fprintf(stderr, "dumper problem, exiting\n");
64                                 exit(1);
65                         }
66
67                         p    += cnt;
68                         size += cnt;
69
70                         if (size >= max)
71                                 break;
72                 }
73         }
74
75         return buf;
76 }
77
78 /**
79  * Dumps the register requirements for either in or out.
80  */
81 static void dump_reg_req(FILE *F, ir_node *n, const ppc32_register_req_t **reqs, int inout) {
82         char *dir = inout ? "out" : "in";
83         int   max = inout ? get_ppc32_n_res(n) : get_irn_arity(n);
84         char *buf = alloca(1024);
85         int   i;
86
87         memset(buf, 0, 1024);
88
89         if (reqs) {
90                 for (i = 0; i < max; i++) {
91                         fprintf(F, "%sreq #%d =", dir, i);
92
93                         if (reqs[i]->req.type == arch_register_req_type_none) {
94                                 fprintf(F, " n/a");
95                         }
96
97                         if (reqs[i]->req.type & arch_register_req_type_normal) {
98                                 fprintf(F, " %s", reqs[i]->req.cls->name);
99                         }
100
101                         if (reqs[i]->req.type & arch_register_req_type_limited) {
102                                 fprintf(F, " %s", get_limited_regs(&reqs[i]->req, buf, 1024));
103                         }
104
105                         if (reqs[i]->req.type & arch_register_req_type_should_be_same) {
106                                 ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->same_pos));
107                         }
108
109                         if (reqs[i]->req.type & arch_register_req_type_should_be_different) {
110                                 ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->different_pos));
111                         }
112
113                         fprintf(F, "\n");
114                 }
115
116                 fprintf(F, "\n");
117         }
118         else {
119                 fprintf(F, "%sreq = N/A\n", dir);
120         }
121 }
122
123
124 /**
125  * Dumper interface for dumping ppc32 nodes in vcg.
126  * @param n        the node to dump
127  * @param F        the output file
128  * @param reason   indicates which kind of information should be dumped
129  * @return 0 on success or != 0 on failure
130  */
131 static int ppc32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
132         ir_mode     *mode = NULL;
133         int          bad  = 0;
134         int          i;
135         ppc32_attr_t *attr;
136         const ppc32_register_req_t **reqs;
137         const arch_register_t     **slots;
138
139         switch (reason) {
140                 case dump_node_opcode_txt:
141                         fprintf(F, "%s", get_irn_opname(n));
142                         break;
143
144                 case dump_node_mode_txt:
145                         mode = get_irn_mode(n);
146
147                         if (mode) {
148                                 fprintf(F, "[%s]", get_mode_name(mode));
149                         }
150                         else {
151                                 fprintf(F, "[?NOMODE?]");
152                         }
153                         break;
154
155                 case dump_node_nodeattr_txt:
156
157                         /* TODO: dump some attributes which should show up */
158                         /* in node name in dump (e.g. consts or the like)  */
159
160                         break;
161
162                 case dump_node_info_txt:
163                         attr = get_ppc32_attr(n);
164                         fprintf(F, "=== ppc attr begin ===\n");
165
166                         /* dump IN requirements */
167                         if (get_irn_arity(n) > 0) {
168                                 reqs = get_ppc32_in_req_all(n);
169                                 dump_reg_req(F, n, reqs, 0);
170                         }
171
172                         /* dump OUT requirements */
173                         if (attr->n_res > 0) {
174                                 reqs = get_ppc32_out_req_all(n);
175                                 dump_reg_req(F, n, reqs, 1);
176                         }
177
178                         /* dump assigned registers */
179                         slots = get_ppc32_slots(n);
180                         if (slots && attr->n_res > 0) {
181                                 for (i = 0; i < attr->n_res; i++) {
182                                         if (slots[i]) {
183                                                 fprintf(F, "reg #%d = %s\n", i, slots[i]->name);
184                                         }
185                                         else {
186                                                 fprintf(F, "reg #%d = n/a\n", i);
187                                         }
188                                 }
189                         }
190                         fprintf(F, "\n");
191
192                         /* dump n_res */
193                         fprintf(F, "n_res = %d\n", get_ppc32_n_res(n));
194
195                         /* dump flags */
196                         fprintf(F, "flags =");
197                         if (attr->flags == arch_irn_flags_none) {
198                                 fprintf(F, " none");
199                         }
200                         else {
201                                 if (attr->flags & arch_irn_flags_dont_spill) {
202                                         fprintf(F, " unspillable");
203                                 }
204                                 if (attr->flags & arch_irn_flags_rematerializable) {
205                                         fprintf(F, " remat");
206                                 }
207                                 if (attr->flags & arch_irn_flags_ignore) {
208                                         fprintf(F, " ignore");
209                                 }
210                         }
211                         fprintf(F, " (%d)\n", attr->flags);
212
213                         /* TODO: dump all additional attributes */
214
215                         fprintf(F, "=== ppc attr end ===\n");
216                         /* end of: case dump_node_info_txt */
217                         break;
218         }
219
220
221         return bad;
222 }
223
224
225
226 /***************************************************************************************************
227  *        _   _                   _       __        _                    _   _               _
228  *       | | | |                 | |     / /       | |                  | | | |             | |
229  *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
230  *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
231  * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
232  *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
233  *                                        __/ |
234  *                                       |___/
235  ***************************************************************************************************/
236
237 /**
238  * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
239  * Firm was made by people hating const :-(
240  */
241 ppc32_attr_t *get_ppc32_attr(const ir_node *node) {
242         assert(is_ppc32_irn(node) && "need ppc node to get attributes");
243         return (ppc32_attr_t *)get_irn_generic_attr((ir_node *)node);
244 }
245
246 /**
247  * Returns the argument register requirements of a ppc node.
248  */
249 const ppc32_register_req_t **get_ppc32_in_req_all(const ir_node *node) {
250         ppc32_attr_t *attr = get_ppc32_attr(node);
251         return attr->in_req;
252 }
253
254 /**
255  * Returns the result register requirements of an ppc node.
256  */
257 const ppc32_register_req_t **get_ppc32_out_req_all(const ir_node *node) {
258         ppc32_attr_t *attr = get_ppc32_attr(node);
259         return attr->out_req;
260 }
261
262 /**
263  * Returns the argument register requirement at position pos of an ppc node.
264  */
265 const ppc32_register_req_t *get_ppc32_in_req(const ir_node *node, int pos) {
266         ppc32_attr_t *attr = get_ppc32_attr(node);
267         return attr->in_req[pos];
268 }
269
270 /**
271  * Returns the result register requirement at position pos of an ppc node.
272  */
273 const ppc32_register_req_t *get_ppc32_out_req(const ir_node *node, int pos) {
274         ppc32_attr_t *attr = get_ppc32_attr(node);
275         return attr->out_req[pos];
276 }
277
278 /**
279  * Sets the OUT register requirements at position pos.
280  */
281 void set_ppc32_req_out(ir_node *node, const ppc32_register_req_t *req, int pos) {
282         ppc32_attr_t *attr   = get_ppc32_attr(node);
283         attr->out_req[pos] = req;
284 }
285
286 /**
287  * Sets the IN register requirements at position pos.
288  */
289 void set_ppc32_req_in(ir_node *node, const ppc32_register_req_t *req, int pos) {
290         ppc32_attr_t *attr  = get_ppc32_attr(node);
291         attr->in_req[pos] = req;
292 }
293
294 /**
295  * Returns the register flag of an ppc node.
296  */
297 arch_irn_flags_t get_ppc32_flags(const ir_node *node) {
298         ppc32_attr_t *attr = get_ppc32_attr(node);
299         return attr->flags;
300 }
301
302 /**
303  * Sets the register flag of an ppc node.
304  */
305 void set_ppc32_flags(const ir_node *node, arch_irn_flags_t flags) {
306         ppc32_attr_t *attr = get_ppc32_attr(node);
307         attr->flags      = flags;
308 }
309
310 /**
311  * Returns the result register slots of an ppc node.
312  */
313 const arch_register_t **get_ppc32_slots(const ir_node *node) {
314         ppc32_attr_t *attr = get_ppc32_attr(node);
315         return attr->slots;
316 }
317
318 /**
319  * Returns the name of the OUT register at position pos.
320  */
321 const char *get_ppc32_out_reg_name(const ir_node *node, int pos) {
322         ppc32_attr_t *attr = get_ppc32_attr(node);
323
324         assert(is_ppc32_irn(node) && "Not an ppc node.");
325         assert(pos < attr->n_res && "Invalid OUT position.");
326         assert(attr->slots[pos]  && "No register assigned");
327
328         return arch_register_get_name(attr->slots[pos]);
329 }
330
331 /**
332  * Returns the index of the OUT register at position pos within its register class.
333  */
334 int get_ppc32_out_regnr(const ir_node *node, int pos) {
335         ppc32_attr_t *attr = get_ppc32_attr(node);
336
337         assert(is_ppc32_irn(node) && "Not an ppc node.");
338         assert(pos < attr->n_res && "Invalid OUT position.");
339         assert(attr->slots[pos]  && "No register assigned");
340
341         return arch_register_get_index(attr->slots[pos]);
342 }
343
344 /**
345  * Returns the OUT register at position pos.
346  */
347 const arch_register_t *get_ppc32_out_reg(const ir_node *node, int pos) {
348         ppc32_attr_t *attr = get_ppc32_attr(node);
349
350         assert(is_ppc32_irn(node) && "Not an ppc node.");
351         assert(pos < attr->n_res && "Invalid OUT position.");
352         assert(attr->slots[pos]  && "No register assigned");
353
354         return attr->slots[pos];
355 }
356
357 /**
358  * Sets the number of results.
359  */
360 void set_ppc32_n_res(ir_node *node, int n_res) {
361         ppc32_attr_t *attr = get_ppc32_attr(node);
362         attr->n_res      = n_res;
363 }
364
365 /**
366  * Returns the number of results.
367  */
368 int get_ppc32_n_res(const ir_node *node) {
369         ppc32_attr_t *attr = get_ppc32_attr(node);
370         return attr->n_res;
371 }
372
373 /**
374  * Sets the type of the constant (if any)
375  * May be either iro_Const or iro_SymConst
376  */
377 /* void set_ppc32_type(const ir_node *node, opcode type) {
378         ppc32_attr_t *attr = get_ppc32_attr(node);
379         attr->type      = type;
380 }  */
381
382 /**
383  * Returns the type of the content (if any)
384  */
385 ppc32_attr_content_type get_ppc32_type(const ir_node *node) {
386         ppc32_attr_t *attr = get_ppc32_attr(node);
387         return attr->content_type;
388 }
389
390 /**
391  * Sets a tarval type content (also updating the content_type)
392  */
393 void set_ppc32_constant_tarval(const ir_node *node, tarval *const_tarval) {
394         ppc32_attr_t *attr = get_ppc32_attr(node);
395         attr->content_type = ppc32_ac_Const;
396         attr->data.constant_tarval = const_tarval;
397 }
398
399 /**
400  * Returns a tarval type constant
401  */
402 tarval *get_ppc32_constant_tarval(const ir_node *node) {
403         ppc32_attr_t *attr = get_ppc32_attr(node);
404         return attr->data.constant_tarval;
405 }
406
407 /**
408  * Sets an ident type constant (also updating the content_type)
409  */
410 void set_ppc32_symconst_ident(const ir_node *node, ident *symconst_ident) {
411         ppc32_attr_t *attr = get_ppc32_attr(node);
412         attr->content_type = ppc32_ac_SymConst;
413         attr->data.symconst_ident = symconst_ident;
414 }
415
416 /**
417  * Returns an ident type constant
418  */
419 ident *get_ppc32_symconst_ident(const ir_node *node) {
420         ppc32_attr_t *attr = get_ppc32_attr(node);
421         return attr->data.symconst_ident;
422 }
423
424
425 /**
426  * Sets an entity (also updating the content_type)
427  */
428 void set_ppc32_frame_entity(const ir_node *node, ir_entity *ent) {
429         ppc32_attr_t *attr = get_ppc32_attr(node);
430         attr->content_type = ppc32_ac_FrameEntity;
431         attr->data.frame_entity = ent;
432 }
433
434 /**
435  * Returns an entity
436  */
437 ir_entity *get_ppc32_frame_entity(const ir_node *node) {
438         ppc32_attr_t *attr = get_ppc32_attr(node);
439         return attr->data.frame_entity;
440 }
441
442 /**
443  * Sets a Rlwimi const (also updating the content_type)
444  */
445 void set_ppc32_rlwimi_const(const ir_node *node, unsigned shift, unsigned maskA, unsigned maskB) {
446         ppc32_attr_t *attr = get_ppc32_attr(node);
447         attr->content_type = ppc32_ac_RlwimiConst;
448         attr->data.rlwimi_const.shift = shift;
449         attr->data.rlwimi_const.maskA = maskA;
450         attr->data.rlwimi_const.maskB = maskB;
451 }
452
453 /**
454  * Returns the rlwimi const structure
455  */
456 rlwimi_const_t *get_ppc32_rlwimi_const(const ir_node *node) {
457         ppc32_attr_t *attr = get_ppc32_attr(node);
458         return &attr->data.rlwimi_const;
459 }
460
461 /**
462  * Sets a Proj number (also updating the content_type)
463  */
464 void set_ppc32_proj_nr(const ir_node *node, int proj_nr) {
465         ppc32_attr_t *attr = get_ppc32_attr(node);
466         attr->content_type = ppc32_ac_BranchProj;
467         attr->data.proj_nr = proj_nr;
468 }
469
470 /**
471  * Returns the proj number
472  */
473 int get_ppc32_proj_nr(const ir_node *node) {
474         ppc32_attr_t *attr = get_ppc32_attr(node);
475         return attr->data.proj_nr;
476 }
477
478 /**
479  * Sets an offset for a memory access (also updating the content_type)
480  */
481 void set_ppc32_offset(const ir_node *node, int offset) {
482         ppc32_attr_t *attr = get_ppc32_attr(node);
483         attr->content_type = ppc32_ac_Offset;
484         attr->data.offset  = offset;
485 }
486
487 /**
488  * Returns the offset
489  */
490 int get_ppc32_offset(const ir_node *node) {
491         ppc32_attr_t *attr = get_ppc32_attr(node);
492         return attr->data.offset;
493 }
494
495 /**
496  * Sets the offset mode (ppc32_ao_None, ppc32_ao_Lo16, ppc32_ao_Hi16 or ppc32_ao_Ha16)
497  */
498 void set_ppc32_offset_mode(const ir_node *node, ppc32_attr_offset_mode mode) {
499         ppc32_attr_t *attr = get_ppc32_attr(node);
500         attr->offset_mode = mode;
501 }
502
503 /**
504  * Returns the offset mode
505  */
506 ppc32_attr_offset_mode get_ppc32_offset_mode(const ir_node *node) {
507         ppc32_attr_t *attr = get_ppc32_attr(node);
508         return attr->offset_mode;
509 }
510
511
512 /**
513  * Initializes ppc specific node attributes
514  */
515 void init_ppc32_attributes(ir_node *node, int flags,
516                                                  const ppc32_register_req_t **in_reqs, const ppc32_register_req_t **out_reqs,
517                                                  const be_execution_unit_t ***execution_units,
518                                                  int n_res, unsigned latency) {
519         ppc32_attr_t *attr = get_ppc32_attr(node);
520
521         attr->flags   = flags;
522         attr->in_req  = in_reqs;
523         attr->out_req = out_reqs;
524         attr->n_res   = n_res;
525
526         attr->content_type = ppc32_ac_None;
527         attr->offset_mode  = ppc32_ao_Illegal;
528         attr->data.empty   = NULL;
529
530         memset((void *)attr->slots, 0, n_res * sizeof(attr->slots[0]));
531 }
532
533
534 /***************************************************************************************
535  *                  _                            _                   _
536  *                 | |                          | |                 | |
537  *  _ __   ___   __| | ___    ___ ___  _ __  ___| |_ _ __ _   _  ___| |_ ___  _ __ ___
538  * | '_ \ / _ \ / _` |/ _ \  / __/ _ \| '_ \/ __| __| '__| | | |/ __| __/ _ \| '__/ __|
539  * | | | | (_) | (_| |  __/ | (_| (_) | | | \__ \ |_| |  | |_| | (__| || (_) | |  \__ \
540  * |_| |_|\___/ \__,_|\___|  \___\___/|_| |_|___/\__|_|   \__,_|\___|\__\___/|_|  |___/
541  *
542  ***************************************************************************************/
543
544 /* Include the generated constructor functions */
545 #include "gen_ppc32_new_nodes.c.inl"