354bf7596f3b457fb7dd8401228f230e3da3d6cb
[libfirm] / ir / be / sparc / sparc_new_nodes.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   This file implements the creation of the achitecture specific firm
23  *          opcodes and the coresponding node constructors for the sparc
24  *          assembler irg.
25  * @version $Id$
26  */
27 #include "config.h"
28
29 #include <stdlib.h>
30
31 #include "irprog_t.h"
32 #include "irgraph_t.h"
33 #include "irnode_t.h"
34 #include "irmode_t.h"
35 #include "ircons_t.h"
36 #include "iropt_t.h"
37 #include "irop.h"
38 #include "irvrfy_t.h"
39 #include "irprintf.h"
40 #include "xmalloc.h"
41
42 #include "../bearch.h"
43
44 #include "sparc_nodes_attr.h"
45 #include "sparc_new_nodes.h"
46 #include "gen_sparc_regalloc_if.h"
47
48 static bool has_symconst_attr(const ir_node *node)
49 {
50         return is_sparc_SymConst(node) || is_sparc_FrameAddr(node);
51 }
52
53 static bool has_load_store_attr(const ir_node *node)
54 {
55         return is_sparc_Ld(node) || is_sparc_St(node) || is_sparc_Ldf(node)
56             || is_sparc_Stf(node);
57 }
58
59 static bool has_jmp_cond_attr(const ir_node *node)
60 {
61         return is_sparc_BXX(node);
62 }
63
64 static bool has_jmp_switch_attr(const ir_node *node)
65 {
66         return is_sparc_SwitchJmp(node);
67 }
68
69 static bool has_save_attr(const ir_node *node)
70 {
71         return is_sparc_Save(node);
72 }
73
74 static bool has_fp_attr(const ir_node *node)
75 {
76         return is_sparc_fadd(node) || is_sparc_fsub(node)
77             || is_sparc_fmul(node) || is_sparc_fdiv(node)
78             || is_sparc_fftoi(node) || is_sparc_fitof(node)
79             || is_sparc_fneg(node);
80 }
81
82 static bool has_fp_conv_attr(const ir_node *node)
83 {
84         return is_sparc_fftof(node);
85 }
86
87 /**
88  * Dumper interface for dumping sparc nodes in vcg.
89  * @param F        the output file
90  * @param n        the node to dump
91  * @param reason   indicates which kind of information should be dumped
92  */
93 static void sparc_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
94 {
95         switch (reason) {
96         case dump_node_opcode_txt:
97                 fprintf(F, "%s", get_irn_opname(n));
98                 break;
99
100         case dump_node_mode_txt:
101                 break;
102
103         case dump_node_info_txt:
104                 arch_dump_reqs_and_registers(F, n);
105                 if (has_save_attr(n)) {
106                         const sparc_save_attr_t *attr = get_sparc_save_attr_const(n);
107                         fprintf(F, "initial stacksize: %d\n", attr->initial_stacksize);
108                 }
109                 if (has_symconst_attr(n)) {
110                         const sparc_symconst_attr_t *attr = get_sparc_symconst_attr_const(n);
111                         ir_fprintf(F, "entity: %+F\n", attr->entity);
112                         fprintf(F, "fp_offset: %d\n", attr->fp_offset);
113                 }
114                 if (has_load_store_attr(n)) {
115                         const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(n);
116                         ir_fprintf(F, "load store mode: %+F\n", attr->load_store_mode);
117                         ir_fprintf(F, "entity: (sign %d) %+F\n", attr->entity_sign,
118                                    attr->entity);
119                         fprintf(F, "offset: %ld\n", attr->offset);
120                         fprintf(F, "is frame entity: %s\n",
121                                 attr->is_frame_entity ? "true" : "false");
122                 }
123                 if (has_jmp_cond_attr(n)) {
124                         const sparc_jmp_cond_attr_t *attr
125                                 = get_sparc_jmp_cond_attr_const(n);
126                         fprintf(F, "pnc: %d (%s)\n", attr->proj_num,
127                                 get_pnc_string(attr->proj_num));
128                         fprintf(F, "unsigned: %s\n", attr->is_unsigned ? "true" : "false");
129                 }
130                 if (has_jmp_switch_attr(n)) {
131                         const sparc_jmp_switch_attr_t *attr
132                                 = get_sparc_jmp_switch_attr_const(n);
133                         fprintf(F, "n projs: %d\n", attr->n_projs);
134                         fprintf(F, "default proj: %ld\n", attr->default_proj_num);
135                 }
136                 if (has_fp_attr(n)) {
137                         const sparc_fp_attr_t *attr = get_sparc_fp_attr_const(n);
138                         ir_fprintf(F, "fp_mode: %+F\n", attr->fp_mode);
139                 }
140                 if (has_fp_conv_attr(n)) {
141                         const sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr_const(n);
142                         ir_fprintf(F, "conv from: %+F\n", attr->src_mode);
143                         ir_fprintf(F, "conv to: %+F\n", attr->dest_mode);
144                 }
145                 break;
146
147         case dump_node_nodeattr_txt:
148                 break;
149         }
150 }
151
152 static void sparc_set_attr_imm(ir_node *res, int immediate_value)
153 {
154         sparc_attr_t *attr = get_irn_generic_attr(res);
155         attr->immediate_value = immediate_value;
156 }
157
158 static void init_sparc_jmp_cond_attr(ir_node *node, int proj_num,
159                                      bool is_unsigned)
160 {
161         sparc_jmp_cond_attr_t *attr = get_sparc_jmp_cond_attr(node);
162         attr->proj_num    = proj_num;
163         attr->is_unsigned = is_unsigned;
164 }
165
166 void set_sparc_jmp_switch_n_projs(ir_node *node, int n_projs)
167 {
168         sparc_jmp_switch_attr_t *attr = get_sparc_jmp_switch_attr(node);
169         attr->n_projs = n_projs;
170 }
171
172 void set_sparc_jmp_switch_default_proj_num(ir_node *node, long def_proj_num)
173 {
174         sparc_jmp_switch_attr_t *attr = get_sparc_jmp_switch_attr(node);
175         attr->default_proj_num = def_proj_num;
176 }
177
178
179
180 int get_sparc_jmp_switch_n_projs(const ir_node *node)
181 {
182         const sparc_jmp_switch_attr_t *attr = get_sparc_jmp_switch_attr_const(node);
183         return attr->n_projs;
184 }
185
186 long get_sparc_jmp_switch_default_proj_num(const ir_node *node)
187 {
188         const sparc_jmp_switch_attr_t *attr = get_sparc_jmp_switch_attr_const(node);
189         return attr->default_proj_num;
190 }
191
192 sparc_attr_t *get_sparc_attr(ir_node *node)
193 {
194         assert(is_sparc_irn(node));
195         return (sparc_attr_t*) get_irn_generic_attr(node);
196 }
197
198 const sparc_attr_t *get_sparc_attr_const(const ir_node *node)
199 {
200         assert(is_sparc_irn(node));
201         return (const sparc_attr_t*) get_irn_generic_attr_const(node);
202 }
203
204 sparc_load_store_attr_t *get_sparc_load_store_attr(ir_node *node)
205 {
206         assert(has_load_store_attr(node));
207         return (sparc_load_store_attr_t*) get_irn_generic_attr_const(node);
208 }
209
210 const sparc_load_store_attr_t *get_sparc_load_store_attr_const(const ir_node *node)
211 {
212         assert(has_load_store_attr(node));
213         return (const sparc_load_store_attr_t*) get_irn_generic_attr_const(node);
214 }
215
216 sparc_symconst_attr_t *get_sparc_symconst_attr(ir_node *node)
217 {
218         assert(has_symconst_attr(node));
219         return (sparc_symconst_attr_t*) get_irn_generic_attr_const(node);
220 }
221
222 const sparc_symconst_attr_t *get_sparc_symconst_attr_const(const ir_node *node)
223 {
224         assert(has_symconst_attr(node));
225         return (const sparc_symconst_attr_t*) get_irn_generic_attr_const(node);
226 }
227
228 sparc_jmp_cond_attr_t *get_sparc_jmp_cond_attr(ir_node *node)
229 {
230         assert(has_jmp_cond_attr(node));
231         return (sparc_jmp_cond_attr_t*) get_irn_generic_attr_const(node);
232 }
233
234 const sparc_jmp_cond_attr_t *get_sparc_jmp_cond_attr_const(const ir_node *node)
235 {
236         assert(has_jmp_cond_attr(node));
237         return (const sparc_jmp_cond_attr_t*) get_irn_generic_attr_const(node);
238 }
239
240 sparc_jmp_switch_attr_t *get_sparc_jmp_switch_attr(ir_node *node)
241 {
242         assert(has_jmp_switch_attr(node));
243         return (sparc_jmp_switch_attr_t*) get_irn_generic_attr_const(node);
244 }
245
246 const sparc_jmp_switch_attr_t *get_sparc_jmp_switch_attr_const(const ir_node *node)
247 {
248         assert(has_jmp_switch_attr(node));
249         return (const sparc_jmp_switch_attr_t*) get_irn_generic_attr_const(node);
250 }
251
252 sparc_save_attr_t *get_sparc_save_attr(ir_node *node)
253 {
254         assert(has_save_attr(node));
255         return (sparc_save_attr_t*) get_irn_generic_attr_const(node);
256 }
257
258 const sparc_save_attr_t *get_sparc_save_attr_const(const ir_node *node)
259 {
260         assert(has_save_attr(node));
261         return (const sparc_save_attr_t*) get_irn_generic_attr_const(node);
262 }
263
264 sparc_fp_attr_t *get_sparc_fp_attr(ir_node *node)
265 {
266         assert(has_fp_attr(node));
267         return (sparc_fp_attr_t*) get_irn_generic_attr(node);
268 }
269
270 const sparc_fp_attr_t *get_sparc_fp_attr_const(const ir_node *node)
271 {
272         assert(has_fp_attr(node));
273         return (const sparc_fp_attr_t*) get_irn_generic_attr_const(node);
274 }
275
276 sparc_fp_conv_attr_t *get_sparc_fp_conv_attr(ir_node *node)
277 {
278         assert(has_fp_conv_attr(node));
279         return (sparc_fp_conv_attr_t*) get_irn_generic_attr(node);
280 }
281
282 const sparc_fp_conv_attr_t *get_sparc_fp_conv_attr_const(const ir_node *node)
283 {
284         assert(has_fp_conv_attr(node));
285         return (const sparc_fp_conv_attr_t*) get_irn_generic_attr_const(node);
286 }
287
288 /**
289  * Returns the argument register requirements of a sparc node.
290  */
291 const arch_register_req_t **get_sparc_in_req_all(const ir_node *node)
292 {
293         const sparc_attr_t *attr = get_sparc_attr_const(node);
294         return attr->in_req;
295 }
296
297 void set_sparc_in_req_all(ir_node *node, const arch_register_req_t **reqs)
298 {
299         sparc_attr_t *attr = get_sparc_attr(node);
300         attr->in_req = reqs;
301 }
302
303 /**
304  * Returns the argument register requirement at position pos of an sparc node.
305  */
306 const arch_register_req_t *get_sparc_in_req(const ir_node *node, int pos)
307 {
308         const sparc_attr_t *attr = get_sparc_attr_const(node);
309         return attr->in_req[pos];
310 }
311
312 /**
313  * Sets the IN register requirements at position pos.
314  */
315 void set_sparc_req_in(ir_node *node, const arch_register_req_t *req, int pos)
316 {
317         sparc_attr_t *attr  = get_sparc_attr(node);
318         attr->in_req[pos] = req;
319 }
320
321 /**
322  * Initializes the nodes attributes.
323  */
324 static void init_sparc_attributes(ir_node *node, arch_irn_flags_t flags,
325                                   const arch_register_req_t **in_reqs,
326                                   const be_execution_unit_t ***execution_units,
327                                   int n_res)
328 {
329         ir_graph        *irg  = get_irn_irg(node);
330         struct obstack  *obst = get_irg_obstack(irg);
331         sparc_attr_t *attr = get_sparc_attr(node);
332         backend_info_t  *info;
333         (void) execution_units;
334
335         arch_irn_set_flags(node, flags);
336         attr->in_req  = in_reqs;
337         attr->is_load_store = false;
338
339         info            = be_get_info(node);
340         info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
341         memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
342 }
343
344 static void init_sparc_load_store_attributes(ir_node *res, ir_mode *ls_mode,
345                                                                                         ir_entity *entity,
346                                                                                         int entity_sign, long offset,
347                                                                                         bool is_frame_entity)
348 {
349         sparc_load_store_attr_t *attr = get_sparc_load_store_attr(res);
350         attr->load_store_mode    = ls_mode;
351         attr->entity             = entity;
352         attr->entity_sign        = entity_sign;
353         attr->is_frame_entity    = is_frame_entity;
354         attr->offset             = offset;
355         attr->base.is_load_store = true;
356 }
357
358 static void init_sparc_symconst_attributes(ir_node *res, ir_entity *entity)
359 {
360         sparc_symconst_attr_t *attr = get_sparc_symconst_attr(res);
361         attr->entity    = entity;
362         attr->fp_offset = 0;
363 }
364
365 static void init_sparc_save_attributes(ir_node *res, int initial_stacksize)
366 {
367         sparc_save_attr_t *attr = get_sparc_save_attr(res);
368         attr->initial_stacksize = initial_stacksize;
369 }
370
371 static void init_sparc_fp_attributes(ir_node *res, ir_mode *fp_mode)
372 {
373         sparc_fp_attr_t *attr = get_sparc_fp_attr(res);
374         attr->fp_mode = fp_mode;
375 }
376
377 static void init_sparc_fp_conv_attributes(ir_node *res, ir_mode *src_mode,
378                                           ir_mode *dest_mode)
379 {
380         sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr(res);
381         attr->src_mode = src_mode;
382         attr->dest_mode = dest_mode;
383 }
384
385 /**
386  * copies sparc attributes of  node
387  */
388 static void sparc_copy_attr(ir_graph *irg, const ir_node *old_node,
389                             ir_node *new_node)
390 {
391         struct obstack     *obst    = get_irg_obstack(irg);
392         const sparc_attr_t *attr_old = get_sparc_attr_const(old_node);
393         sparc_attr_t       *attr_new = get_sparc_attr(new_node);
394         backend_info_t     *old_info = be_get_info(old_node);
395         backend_info_t     *new_info = be_get_info(new_node);
396
397         /* copy the attributes */
398         memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
399         /* copy out flags */
400         new_info->out_infos =
401                 DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
402 }
403
404 /**
405  * compare some node's attributes
406  */
407 static int cmp_attr_sparc(ir_node *a, ir_node *b)
408 {
409         const sparc_attr_t *attr_a = get_sparc_attr_const(a);
410         const sparc_attr_t *attr_b = get_sparc_attr_const(b);
411
412         return attr_a->immediate_value != attr_b->immediate_value
413                         || attr_a->is_load_store != attr_b->is_load_store;
414 }
415
416 static int cmp_attr_sparc_load_store(ir_node *a, ir_node *b)
417 {
418         const sparc_load_store_attr_t *attr_a = get_sparc_load_store_attr_const(a);
419         const sparc_load_store_attr_t *attr_b = get_sparc_load_store_attr_const(b);
420
421         if (cmp_attr_sparc(a, b))
422                 return 1;
423
424         return attr_a->entity != attr_b->entity
425                         || attr_a->entity_sign != attr_b->entity_sign
426                         || attr_a->is_frame_entity != attr_b->is_frame_entity
427                         || attr_a->load_store_mode != attr_b->load_store_mode
428                         || attr_a->offset != attr_b->offset;
429 }
430
431 static int cmp_attr_sparc_symconst(ir_node *a, ir_node *b)
432 {
433         const sparc_symconst_attr_t *attr_a = get_sparc_symconst_attr_const(a);
434         const sparc_symconst_attr_t *attr_b = get_sparc_symconst_attr_const(b);
435
436         if (cmp_attr_sparc(a, b))
437                 return 1;
438
439         return attr_a->entity != attr_b->entity
440                         || attr_a->fp_offset != attr_b->fp_offset;
441 }
442
443 static int cmp_attr_sparc_jmp_cond(ir_node *a, ir_node *b)
444 {
445         const sparc_jmp_cond_attr_t *attr_a = get_sparc_jmp_cond_attr_const(a);
446         const sparc_jmp_cond_attr_t *attr_b = get_sparc_jmp_cond_attr_const(b);
447
448         if (cmp_attr_sparc(a, b))
449                 return 1;
450
451         return attr_a->proj_num != attr_b->proj_num
452                 || attr_a->is_unsigned != attr_b->is_unsigned;
453 }
454
455 static int cmp_attr_sparc_jmp_switch(ir_node *a, ir_node *b)
456 {
457         const sparc_jmp_switch_attr_t *attr_a = get_sparc_jmp_switch_attr_const(a);
458         const sparc_jmp_switch_attr_t *attr_b = get_sparc_jmp_switch_attr_const(b);
459
460         if (cmp_attr_sparc(a, b))
461                 return 1;
462
463         return attr_a->default_proj_num != attr_b->default_proj_num
464                         || attr_a->n_projs != attr_b->n_projs;
465 }
466
467 static int cmp_attr_sparc_save(ir_node *a, ir_node *b)
468 {
469         const sparc_save_attr_t *attr_a = get_sparc_save_attr_const(a);
470         const sparc_save_attr_t *attr_b = get_sparc_save_attr_const(b);
471
472         if (cmp_attr_sparc(a, b))
473                 return 1;
474
475         return attr_a->initial_stacksize != attr_b->initial_stacksize;
476 }
477
478 static int cmp_attr_sparc_fp(ir_node *a, ir_node *b)
479 {
480         const sparc_fp_attr_t *attr_a = get_sparc_fp_attr_const(a);
481         const sparc_fp_attr_t *attr_b = get_sparc_fp_attr_const(b);
482
483         if (cmp_attr_sparc(a, b))
484                 return 1;
485
486         return attr_a->fp_mode != attr_b->fp_mode;
487 }
488
489 static int cmp_attr_sparc_fp_conv(ir_node *a, ir_node *b)
490 {
491         const sparc_fp_conv_attr_t *attr_a = get_sparc_fp_conv_attr_const(a);
492         const sparc_fp_conv_attr_t *attr_b = get_sparc_fp_conv_attr_const(b);
493
494         if (cmp_attr_sparc(a, b))
495                 return 1;
496
497         return attr_a->src_mode != attr_b->src_mode
498             || attr_a->dest_mode != attr_b->dest_mode;;
499 }
500
501 /* Include the generated constructor functions */
502 #include "gen_sparc_new_nodes.c.inl"