big refactoring of arch_XXX functions
[libfirm] / ir / be / arm / arm_new_nodes.c
1 /*
2  * Copyright (C) 1995-2011 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 architecture specific firm
23  *         opcodes and the corresponding node constructors for the arm
24  *         assembler irg.
25  * @author Oliver Richter, Tobias Gneist
26  * @version $Id$
27  */
28 #include "config.h"
29
30 #include <stdlib.h>
31 #include <stdbool.h>
32
33 #include "irprog_t.h"
34 #include "irgraph_t.h"
35 #include "irnode_t.h"
36 #include "irmode_t.h"
37 #include "ircons_t.h"
38 #include "iropt_t.h"
39 #include "irop.h"
40 #include "irprintf.h"
41 #include "xmalloc.h"
42
43 #include "../bearch.h"
44
45 #include "arm_nodes_attr.h"
46 #include "arm_new_nodes.h"
47 #include "arm_optimize.h"
48
49 #include "../beabi.h"
50 #include "bearch_arm_t.h"
51
52 const char *arm_get_fpa_imm_name(long imm_value)
53 {
54         static const char *fpa_imm[] = {
55                 "0",
56                 "1",
57                 "2",
58                 "3",
59                 "4",
60                 "5",
61                 "10",
62                 "0.5"
63         };
64         return fpa_imm[imm_value];
65 }
66
67 static bool arm_has_symconst_attr(const ir_node *node)
68 {
69         return is_arm_SymConst(node) || is_arm_FrameAddr(node) || is_arm_Bl(node);
70 }
71
72 static bool has_load_store_attr(const ir_node *node)
73 {
74         return is_arm_Ldr(node) || is_arm_Str(node) || is_arm_LinkLdrPC(node)
75                 || is_arm_Ldf(node) || is_arm_Stf(node);
76 }
77
78 static bool has_shifter_operand(const ir_node *node)
79 {
80         return is_arm_Add(node) || is_arm_And(node) || is_arm_Or(node)
81                 || is_arm_Eor(node) || is_arm_Bic(node) || is_arm_Sub(node)
82                 || is_arm_Rsb(node) || is_arm_Mov(node) || is_arm_Mvn(node)
83                 || is_arm_Cmp(node) || is_arm_Tst(node) || is_arm_LinkMovPC(node);
84 }
85
86 static bool has_cmp_attr(const ir_node *node)
87 {
88         return is_arm_Cmp(node) || is_arm_Tst(node);
89 }
90
91 static bool has_farith_attr(const ir_node *node)
92 {
93         return is_arm_Adf(node) || is_arm_Muf(node) || is_arm_Suf(node)
94             || is_arm_Dvf(node) || is_arm_Mvf(node) || is_arm_FltX(node);
95 }
96
97 /**
98  * Dumper interface for dumping arm nodes in vcg.
99  * @param F        the output file
100  * @param n        the node to dump
101  * @param reason   indicates which kind of information should be dumped
102  */
103 static void arm_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
104 {
105         switch (reason) {
106         case dump_node_opcode_txt:
107                 fprintf(F, "%s", get_irn_opname(n));
108
109                 if (arm_has_symconst_attr(n)) {
110                         const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
111                         if (attr->entity != NULL) {
112                                 fputc(' ', F);
113                                 fputs(get_entity_name(attr->entity), F);
114                         }
115                 }
116                 break;
117
118         case dump_node_mode_txt:
119                 /* mode isn't relevant in the backend */
120                 break;
121
122         case dump_node_nodeattr_txt:
123                 /* TODO: dump shift modifiers */
124                 break;
125
126         case dump_node_info_txt:
127                 arch_dump_reqs_and_registers(F, n);
128
129                 if (has_load_store_attr(n)) {
130                         const arm_load_store_attr_t *attr
131                                 = get_arm_load_store_attr_const(n);
132                         ir_fprintf(F, "load_store_mode = %+F\n", attr->load_store_mode);
133                         ir_fprintf(F, "entity = %+F\n", attr->entity);
134                         fprintf(F, "offset = %ld\n", attr->offset);
135                         fprintf(F, "is_frame_entity = %s\n",
136                                         attr->is_frame_entity ? "yes" : "no");
137                         fprintf(F, "entity_sign = %s\n",
138                                         attr->entity_sign ? "yes" : "no");
139                 }
140                 if (has_shifter_operand(n)) {
141                         const arm_shifter_operand_t *attr
142                                 = get_arm_shifter_operand_attr_const(n);
143                         switch (attr->shift_modifier) {
144                         case ARM_SHF_REG:
145                                 break;
146                         case ARM_SHF_IMM:
147                                 fprintf(F, "modifier = imm %d ror %d\n",
148                                                 attr->immediate_value, attr->shift_immediate);
149                                 break;
150                         case ARM_SHF_ASR_IMM:
151                                 fprintf(F, "modifier = V >>s %d\n", attr->shift_immediate);
152                                 break;
153                         case ARM_SHF_ASR_REG:
154                                 fprintf(F, "modifier = V >>s R\n");
155                                 break;
156                         case ARM_SHF_LSL_IMM:
157                                 fprintf(F, "modifier = V << %d\n", attr->shift_immediate);
158                                 break;
159                         case ARM_SHF_LSL_REG:
160                                 fprintf(F, "modifier = V << R\n");
161                                 break;
162                         case ARM_SHF_LSR_IMM:
163                                 fprintf(F, "modifier = V >> %d\n", attr->shift_immediate);
164                                 break;
165                         case ARM_SHF_LSR_REG:
166                                 fprintf(F, "modifier = V >> R\n");
167                                 break;
168                         case ARM_SHF_ROR_IMM:
169                                 fprintf(F, "modifier = V ROR %d\n", attr->shift_immediate);
170                                 break;
171                         case ARM_SHF_ROR_REG:
172                                 fprintf(F, "modifier = V ROR R\n");
173                                 break;
174                         case ARM_SHF_RRX:
175                                 fprintf(F, "modifier = RRX\n");
176                                 break;
177                         default:
178                         case ARM_SHF_INVALID:
179                                 fprintf(F, "modifier = INVALID SHIFT MODIFIER\n");
180                                 break;
181                         }
182                 }
183                 if (has_cmp_attr(n)) {
184                         const arm_cmp_attr_t *attr = get_arm_cmp_attr_const(n);
185                         fprintf(F, "cmp_attr =");
186                         if (attr->is_unsigned) {
187                                 fprintf(F, " unsigned");
188                         }
189                         if (attr->ins_permuted) {
190                                 fprintf(F, " inputs swapped");
191                         }
192                         fputc('\n', F);
193                 }
194                 if (arm_has_symconst_attr(n)) {
195                         const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
196
197                         fprintf(F, "entity = ");
198                         if (attr->entity != NULL) {
199                                 fprintf(F, "'%s'", get_entity_name(attr->entity));
200                         } else {
201                                 fputs("NULL", F);
202                         }
203                         fputc('\n', F);
204                         fprintf(F, "frame offset = %d\n", attr->fp_offset);
205                 }
206                 if (has_farith_attr(n)) {
207                         const arm_farith_attr_t *attr = get_arm_farith_attr_const(n);
208                         ir_fprintf(F, "arithmetic mode = %+F\n", attr->mode);
209                 }
210                 break;
211         }
212 }
213
214 arm_attr_t *get_arm_attr(ir_node *node)
215 {
216         assert(is_arm_irn(node) && "need arm node to get attributes");
217         return (arm_attr_t*)get_irn_generic_attr(node);
218 }
219
220 const arm_attr_t *get_arm_attr_const(const ir_node *node)
221 {
222         assert(is_arm_irn(node) && "need arm node to get attributes");
223         return (const arm_attr_t*)get_irn_generic_attr_const(node);
224 }
225
226 static bool has_symconst_attr(const ir_node *node)
227 {
228         return is_arm_SymConst(node) || is_arm_FrameAddr(node) || is_arm_Bl(node);
229 }
230
231 arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node)
232 {
233         assert(has_symconst_attr(node));
234         return (arm_SymConst_attr_t*)get_irn_generic_attr(node);
235 }
236
237 const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node)
238 {
239         assert(has_symconst_attr(node));
240         return (const arm_SymConst_attr_t*)get_irn_generic_attr_const(node);
241 }
242
243 static const arm_fConst_attr_t *get_arm_fConst_attr_const(const ir_node *node)
244 {
245         assert(is_arm_fConst(node));
246         return (const arm_fConst_attr_t*)get_irn_generic_attr_const(node);
247 }
248
249 static arm_fConst_attr_t *get_arm_fConst_attr(ir_node *node)
250 {
251         assert(is_arm_fConst(node));
252         return (arm_fConst_attr_t*)get_irn_generic_attr(node);
253 }
254
255 arm_farith_attr_t *get_arm_farith_attr(ir_node *node)
256 {
257         assert(has_farith_attr(node));
258         return (arm_farith_attr_t*)get_irn_generic_attr(node);
259 }
260
261 const arm_farith_attr_t *get_arm_farith_attr_const(const ir_node *node)
262 {
263         assert(has_farith_attr(node));
264         return (const arm_farith_attr_t*)get_irn_generic_attr_const(node);
265 }
266
267 arm_CondJmp_attr_t *get_arm_CondJmp_attr(ir_node *node)
268 {
269         assert(is_arm_B(node));
270         return (arm_CondJmp_attr_t*)get_irn_generic_attr(node);
271 }
272
273 const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node)
274 {
275         assert(is_arm_B(node));
276         return (const arm_CondJmp_attr_t*)get_irn_generic_attr_const(node);
277 }
278
279 arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr(ir_node *node)
280 {
281         assert(is_arm_SwitchJmp(node));
282         return (arm_SwitchJmp_attr_t*)get_irn_generic_attr(node);
283 }
284
285 const arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr_const(const ir_node *node)
286 {
287         assert(is_arm_SwitchJmp(node));
288         return (const arm_SwitchJmp_attr_t*)get_irn_generic_attr_const(node);
289 }
290
291 arm_CopyB_attr_t *get_arm_CopyB_attr(ir_node *node)
292 {
293         assert(is_arm_CopyB(node));
294         return (arm_CopyB_attr_t*)get_irn_generic_attr(node);
295 }
296
297 const arm_CopyB_attr_t *get_arm_CopyB_attr_const(const ir_node *node)
298 {
299         assert(is_arm_CopyB(node));
300         return (const arm_CopyB_attr_t*)get_irn_generic_attr_const(node);
301 }
302
303 ir_tarval *get_fConst_value(const ir_node *node)
304 {
305         const arm_fConst_attr_t *attr = get_arm_fConst_attr_const(node);
306         return attr->tv;
307 }
308
309 void set_fConst_value(ir_node *node, ir_tarval *tv)
310 {
311         arm_fConst_attr_t *attr = get_arm_fConst_attr(node);
312         attr->tv = tv;
313 }
314
315 ir_relation get_arm_CondJmp_relation(const ir_node *node)
316 {
317         const arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr_const(node);
318         return attr->relation;
319 }
320
321 void set_arm_CondJmp_relation(ir_node *node, ir_relation relation)
322 {
323         arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr(node);
324         attr->relation = relation;
325 }
326
327 int get_arm_SwitchJmp_n_projs(const ir_node *node)
328 {
329         const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
330         return attr->n_projs;
331 }
332
333 void set_arm_SwitchJmp_n_projs(ir_node *node, int n_projs)
334 {
335         arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
336         attr->n_projs = n_projs;
337 }
338
339 long get_arm_SwitchJmp_default_proj_num(const ir_node *node)
340 {
341         const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
342         return attr->default_proj_num;
343 }
344
345 void set_arm_SwitchJmp_default_proj_num(ir_node *node, long default_proj_num)
346 {
347         arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
348         attr->default_proj_num = default_proj_num;
349 }
350
351 /* Set the ARM machine node attributes to default values. */
352 static void init_arm_attributes(ir_node *node, arch_irn_flags_t flags,
353                          const arch_register_req_t ** in_reqs,
354                          const be_execution_unit_t ***execution_units,
355                                                  int n_res)
356 {
357         ir_graph       *irg  = get_irn_irg(node);
358         struct obstack *obst = get_irg_obstack(irg);
359         arm_attr_t     *attr = get_arm_attr(node);
360         backend_info_t *info;
361         (void) execution_units;
362
363         arch_set_irn_flags(node, flags);
364         arch_set_irn_register_reqs_in(node, in_reqs);
365         attr->is_load_store    = false;
366
367         info            = be_get_info(node);
368         info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
369         memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
370 }
371
372 static void init_arm_load_store_attributes(ir_node *res, ir_mode *ls_mode,
373                                            ir_entity *entity,
374                                            int entity_sign, long offset,
375                                            bool is_frame_entity)
376 {
377         arm_load_store_attr_t *attr = get_arm_load_store_attr(res);
378         attr->load_store_mode    = ls_mode;
379         attr->entity             = entity;
380         attr->entity_sign        = entity_sign;
381         attr->is_frame_entity    = is_frame_entity;
382         attr->offset             = offset;
383         attr->base.is_load_store = true;
384 }
385
386 static void init_arm_shifter_operand(ir_node *res, unsigned immediate_value,
387                                      arm_shift_modifier_t shift_modifier,
388                                      unsigned shift_immediate)
389 {
390         arm_shifter_operand_t *attr = get_arm_shifter_operand_attr(res);
391         attr->immediate_value = immediate_value;
392         attr->shift_modifier  = shift_modifier;
393         attr->shift_immediate = shift_immediate;
394 }
395
396 static void init_arm_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
397 {
398         arm_cmp_attr_t *attr = get_arm_cmp_attr(res);
399         attr->ins_permuted = ins_permuted;
400         attr->is_unsigned  = is_unsigned;
401 }
402
403 static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity,
404                                          int symconst_offset)
405 {
406         arm_SymConst_attr_t *attr = get_arm_SymConst_attr(res);
407         attr->entity    = entity;
408         attr->fp_offset = symconst_offset;
409 }
410
411 static void init_arm_farith_attributes(ir_node *res, ir_mode *mode)
412 {
413         arm_farith_attr_t *attr = get_arm_farith_attr(res);
414         attr->mode = mode;
415 }
416
417 static void init_arm_CopyB_attributes(ir_node *res, unsigned size)
418 {
419         arm_CopyB_attr_t *attr = get_arm_CopyB_attr(res);
420         attr->size = size;
421 }
422
423 static int cmp_attr_arm(const ir_node *a, const ir_node *b)
424 {
425         (void) a;
426         (void) b;
427         return 0;
428 }
429
430 static int cmp_attr_arm_SymConst(const ir_node *a, const ir_node *b)
431 {
432         const arm_SymConst_attr_t *attr_a;
433         const arm_SymConst_attr_t *attr_b;
434
435         if (cmp_attr_arm(a, b))
436                 return 1;
437
438         attr_a = get_arm_SymConst_attr_const(a);
439         attr_b = get_arm_SymConst_attr_const(b);
440         return attr_a->entity != attr_b->entity
441                 || attr_a->fp_offset != attr_b->fp_offset;
442 }
443
444 static int cmp_attr_arm_CopyB(const ir_node *a, const ir_node *b)
445 {
446         const arm_CopyB_attr_t *attr_a;
447         const arm_CopyB_attr_t *attr_b;
448
449         if (cmp_attr_arm(a, b))
450                 return 1;
451
452         attr_a = get_arm_CopyB_attr_const(a);
453         attr_b = get_arm_CopyB_attr_const(b);
454         return attr_a->size != attr_b->size;
455 }
456
457 static int cmp_attr_arm_CondJmp(const ir_node *a, const ir_node *b)
458 {
459         (void) a;
460         (void) b;
461         /* never identical */
462         return 1;
463 }
464
465 static int cmp_attr_arm_SwitchJmp(const ir_node *a, const ir_node *b)
466 {
467         (void) a;
468         (void) b;
469         /* never identical */
470         return 1;
471 }
472
473 static int cmp_attr_arm_fConst(const ir_node *a, const ir_node *b)
474 {
475         const arm_fConst_attr_t *attr_a;
476         const arm_fConst_attr_t *attr_b;
477
478         if (cmp_attr_arm(a, b))
479                 return 1;
480
481         attr_a = get_arm_fConst_attr_const(a);
482         attr_b = get_arm_fConst_attr_const(b);
483
484         return attr_a->tv != attr_b->tv;
485 }
486
487
488 arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node)
489 {
490         return (arm_load_store_attr_t*) get_irn_generic_attr(node);
491 }
492
493 const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node)
494 {
495         return (const arm_load_store_attr_t*) get_irn_generic_attr_const(node);
496 }
497
498 arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node)
499 {
500         return (arm_shifter_operand_t*) get_irn_generic_attr(node);
501 }
502
503 const arm_shifter_operand_t *get_arm_shifter_operand_attr_const(
504                 const ir_node *node)
505 {
506         return (const arm_shifter_operand_t*) get_irn_generic_attr_const(node);
507 }
508
509 arm_cmp_attr_t *get_arm_cmp_attr(ir_node *node)
510 {
511         return (arm_cmp_attr_t*) get_irn_generic_attr(node);
512 }
513
514 const arm_cmp_attr_t *get_arm_cmp_attr_const(const ir_node *node)
515 {
516         return (const arm_cmp_attr_t*) get_irn_generic_attr_const(node);
517 }
518
519 static int cmp_attr_arm_load_store(const ir_node *a, const ir_node *b)
520 {
521         const arm_load_store_attr_t *attr_a;
522         const arm_load_store_attr_t *attr_b;
523
524         if (cmp_attr_arm(a, b))
525                 return 1;
526
527         attr_a = get_arm_load_store_attr_const(a);
528         attr_b = get_arm_load_store_attr_const(b);
529         if (attr_a->entity != attr_b->entity
530                         || attr_a->entity_sign != attr_b->entity_sign
531                         || attr_a->offset != attr_b->offset)
532                 return 1;
533
534         return 0;
535 }
536
537 static int cmp_attr_arm_shifter_operand(const ir_node *a, const ir_node *b)
538 {
539         const arm_shifter_operand_t *attr_a;
540         const arm_shifter_operand_t *attr_b;
541
542         if (cmp_attr_arm(a, b))
543                 return 1;
544
545         attr_a = get_arm_shifter_operand_attr_const(a);
546         attr_b = get_arm_shifter_operand_attr_const(b);
547         if (attr_a->shift_modifier != attr_b->shift_modifier
548                         || attr_a->immediate_value != attr_b->immediate_value
549                         || attr_a->shift_immediate != attr_b->shift_immediate)
550                 return 1;
551
552         return 0;
553 }
554
555 static int cmp_attr_arm_cmp(const ir_node *a, const ir_node *b)
556 {
557         const arm_cmp_attr_t *attr_a;
558         const arm_cmp_attr_t *attr_b;
559
560         if (cmp_attr_arm(a, b))
561                 return 1;
562
563         attr_a = get_arm_cmp_attr_const(a);
564         attr_b = get_arm_cmp_attr_const(b);
565         if (attr_a->ins_permuted != attr_b->ins_permuted
566                         || attr_a->is_unsigned != attr_b->is_unsigned)
567                 return 1;
568         return 0;
569 }
570
571 static int cmp_attr_arm_farith(const ir_node *a, const ir_node *b)
572 {
573         const arm_farith_attr_t *attr_a;
574         const arm_farith_attr_t *attr_b;
575
576         if (cmp_attr_arm(a, b))
577                 return 1;
578
579         attr_a = get_arm_farith_attr_const(a);
580         attr_b = get_arm_farith_attr_const(b);
581         return attr_a->mode != attr_b->mode;
582 }
583
584 /** copies the ARM attributes of a node. */
585 static void arm_copy_attr(ir_graph *irg, const ir_node *old_node,
586                           ir_node *new_node)
587 {
588         struct obstack   *obst    = get_irg_obstack(irg);
589         const arm_attr_t *attr_old = get_arm_attr_const(old_node);
590         arm_attr_t       *attr_new = get_arm_attr(new_node);
591         backend_info_t   *old_info = be_get_info(old_node);
592         backend_info_t   *new_info = be_get_info(new_node);
593
594         /* copy the attributes */
595         memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
596
597         /* copy out flags */
598         new_info->flags = old_info->flags;
599         new_info->out_infos =
600                 DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
601         new_info->in_reqs = old_info->in_reqs;
602 }
603
604
605 /* Include the generated constructor functions */
606 #include "gen_arm_new_nodes.c.inl"