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