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