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