- various updates to sparc backend
[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
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 "irvrfy_t.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 /**
53  * Return the fpa immediate from the encoding.
54  */
55 const char *arm_get_fpa_imm_name(long imm_value)
56 {
57         static const char *fpa_imm[] = {
58                 "0",
59                 "1",
60                 "2",
61                 "3",
62                 "4",
63                 "5",
64                 "10",
65                 "0.5"
66         };
67         return fpa_imm[imm_value];
68 }
69
70
71 /**
72  * Dumper interface for dumping arm nodes in vcg.
73  * @param n        the node to dump
74  * @param F        the output file
75  * @param reason   indicates which kind of information should be dumped
76  * @return 0 on success or != 0 on failure
77  */
78 static int arm_dump_node(ir_node *n, FILE *F, dump_reason_t reason)
79 {
80         ir_mode     *mode = NULL;
81         //arm_attr_t  *attr = get_arm_attr(n);
82
83         switch (reason) {
84                 case dump_node_opcode_txt:
85                         fprintf(F, "%s", get_irn_opname(n));
86                         break;
87
88                 case dump_node_mode_txt:
89                         mode = get_irn_mode(n);
90
91                         if (mode) {
92                                 fprintf(F, "[%s]", get_mode_name(mode));
93                         }
94                         else {
95                                 fprintf(F, "[?NOMODE?]");
96                         }
97                         break;
98
99                 case dump_node_nodeattr_txt:
100                         /* TODO: dump shift modifiers */
101                         break;
102
103                 case dump_node_info_txt:
104                         arch_dump_reqs_and_registers(F, n);
105
106                         if (is_arm_CopyB(n)) {
107                                 //fprintf(F, "size = %lu\n", get_arm_imm_value(n));
108                         } else {
109                                 /* TODO */
110 #if 0
111                                 long v =  get_arm_imm_value(n);
112                                 if (ARM_GET_FPA_IMM(attr)) {
113                                         fprintf(F, "immediate float value = %s\n", arm_get_fpa_imm_name(v));
114                                 } else {
115                                         fprintf(F, "immediate value = %ld (0x%08lx)\n", v, v);
116                                 }
117 #endif
118                         }
119
120 #if 0
121                         if (is_arm_CmpBra(n) && get_arm_CondJmp_proj_num(n) >= 0) {
122                                 fprintf(F, "proj_num = (%d)\n", get_arm_CondJmp_proj_num(n));
123                         }
124 #endif
125                         break;
126         }
127
128         return 0;
129 }
130
131
132 /* Returns the attributes of a generic Arm node. */
133 arm_attr_t *get_arm_attr(ir_node *node)
134 {
135         assert(is_arm_irn(node) && "need arm node to get attributes");
136         return get_irn_generic_attr(node);
137 }
138
139 const arm_attr_t *get_arm_attr_const(const ir_node *node)
140 {
141         assert(is_arm_irn(node) && "need arm node to get attributes");
142         return get_irn_generic_attr_const(node);
143 }
144
145 /**
146  * Returns the attributes of an ARM SymConst node.
147  */
148 arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node)
149 {
150         assert(is_arm_SymConst(node) || is_arm_FrameAddr(node));
151         return get_irn_generic_attr(node);
152 }
153
154 const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node)
155 {
156         assert(is_arm_SymConst(node) || is_arm_FrameAddr(node));
157         return get_irn_generic_attr_const(node);
158 }
159
160 static const arm_fpaConst_attr_t *get_arm_fpaConst_attr_const(const ir_node *node)
161 {
162         const arm_attr_t          *attr     = get_arm_attr_const(node);
163         const arm_fpaConst_attr_t *fpa_attr = CONST_CAST_ARM_ATTR(arm_fpaConst_attr_t, attr);
164
165         return fpa_attr;
166 }
167
168 static arm_fpaConst_attr_t *get_arm_fpaConst_attr(ir_node *node)
169 {
170         arm_attr_t          *attr     = get_arm_attr(node);
171         arm_fpaConst_attr_t *fpa_attr = CAST_ARM_ATTR(arm_fpaConst_attr_t, attr);
172
173         return fpa_attr;
174 }
175
176 /* Returns the attributes of a CondJmp node. */
177 arm_CondJmp_attr_t *get_arm_CondJmp_attr(ir_node *node)
178 {
179         assert(is_arm_B(node));
180         return get_irn_generic_attr(node);
181 }
182
183 const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node)
184 {
185         assert(is_arm_B(node));
186         return get_irn_generic_attr_const(node);
187 }
188
189 /* Returns the attributes of a SwitchJmp node. */
190 arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr(ir_node *node)
191 {
192         assert(is_arm_SwitchJmp(node));
193         return get_irn_generic_attr(node);
194 }
195
196 const arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr_const(const ir_node *node)
197 {
198         assert(is_arm_SwitchJmp(node));
199         return get_irn_generic_attr_const(node);
200 }
201
202 /**
203  * Returns the argument register requirements of a arm node.
204  */
205 const arch_register_req_t **get_arm_in_req_all(const ir_node *node)
206 {
207         const arm_attr_t *attr = get_arm_attr_const(node);
208         return attr->in_req;
209 }
210
211 /**
212  * Returns the argument register requirement at position pos of an arm node.
213  */
214 const arch_register_req_t *get_arm_in_req(const ir_node *node, int pos)
215 {
216         const arm_attr_t *attr = get_arm_attr_const(node);
217         return attr->in_req[pos];
218 }
219
220 /**
221  * Sets the IN register requirements at position pos.
222  */
223 void set_arm_req_in(ir_node *node, const arch_register_req_t *req, int pos)
224 {
225         arm_attr_t *attr  = get_arm_attr(node);
226         attr->in_req[pos] = req;
227 }
228
229 /**
230  * Returns the fpaConst value
231  */
232 tarval *get_fpaConst_value(const ir_node *node)
233 {
234         const arm_fpaConst_attr_t *attr = get_arm_fpaConst_attr_const(node);
235         return attr->tv;
236 }
237
238 /**
239  * Sets the tarval value
240  */
241 void set_fpaConst_value(ir_node *node, tarval *tv)
242 {
243         arm_fpaConst_attr_t *attr = get_arm_fpaConst_attr(node);
244         attr->tv = tv;
245 }
246
247 /**
248  * Returns the proj num
249  */
250 int get_arm_CondJmp_proj_num(const ir_node *node)
251 {
252         const arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr_const(node);
253         return attr->proj_num;
254 }
255
256 /**
257  * Sets the proj num
258  */
259 void set_arm_CondJmp_proj_num(ir_node *node, int proj_num)
260 {
261         arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr(node);
262         attr->proj_num   = proj_num;
263 }
264
265 /**
266  * Returns the number of projs of a SwitchJmp.
267  */
268 int get_arm_SwitchJmp_n_projs(const ir_node *node)
269 {
270         const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
271         return attr->n_projs;
272 }
273
274 /**
275  * Sets the number of projs.
276  */
277 void set_arm_SwitchJmp_n_projs(ir_node *node, int n_projs)
278 {
279         arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
280         attr->n_projs = n_projs;
281 }
282
283 /**
284  * Returns the default_proj_num.
285  */
286 long get_arm_SwitchJmp_default_proj_num(const ir_node *node)
287 {
288         const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
289         return attr->default_proj_num;
290 }
291
292 /**
293  * Sets the default_proj_num.
294  */
295 void set_arm_SwitchJmp_default_proj_num(ir_node *node, long default_proj_num)
296 {
297         arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
298         attr->default_proj_num = default_proj_num;
299 }
300
301 /* Set the ARM machine node attributes to default values. */
302 static void init_arm_attributes(ir_node *node, int flags,
303                          const arch_register_req_t ** in_reqs,
304                          const be_execution_unit_t ***execution_units,
305                                                  int n_res)
306 {
307         ir_graph       *irg  = get_irn_irg(node);
308         struct obstack *obst = get_irg_obstack(irg);
309         arm_attr_t     *attr = get_arm_attr(node);
310         backend_info_t *info;
311         (void) execution_units;
312
313         arch_irn_set_flags(node, flags);
314         attr->in_req           = in_reqs;
315         attr->instr_fl         = 0;
316
317         info            = be_get_info(node);
318         info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
319         memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
320 }
321
322 static void init_arm_load_store_attributes(ir_node *res, ir_mode *ls_mode,
323                                            ir_entity *entity,
324                                            int entity_sign, long offset,
325                                            bool is_frame_entity)
326 {
327         arm_load_store_attr_t *attr = get_irn_generic_attr(res);
328         attr->load_store_mode    = ls_mode;
329         attr->entity             = entity;
330         attr->entity_sign        = entity_sign;
331         attr->is_frame_entity    = is_frame_entity;
332         attr->offset             = offset;
333         attr->base.is_load_store = true;
334 }
335
336 static void init_arm_shifter_operand(ir_node *res, unsigned immediate_value,
337                                      arm_shift_modifier shift_modifier,
338                                      unsigned shift_immediate)
339 {
340         arm_shifter_operand_t *attr = get_irn_generic_attr(res);
341         attr->immediate_value = immediate_value;
342         attr->shift_modifier  = shift_modifier;
343         attr->shift_immediate = shift_immediate;
344 }
345
346 static void init_arm_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
347 {
348         arm_cmp_attr_t *attr = get_irn_generic_attr(res);
349         attr->ins_permuted = ins_permuted;
350         attr->is_unsigned  = is_unsigned;
351 }
352
353 static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity)
354 {
355         arm_SymConst_attr_t *attr = get_irn_generic_attr(res);
356         attr->entity    = entity;
357         attr->fp_offset = 0;
358 }
359
360 static void init_arm_CopyB_attributes(ir_node *res, unsigned size)
361 {
362         arm_CopyB_attr_t *attr = get_irn_generic_attr(res);
363         attr->size = size;
364 }
365
366 static int cmp_attr_arm(ir_node *a, ir_node *b)
367 {
368         arm_attr_t *attr_a = get_irn_generic_attr(a);
369         arm_attr_t *attr_b = get_irn_generic_attr(b);
370         return attr_a->instr_fl != attr_b->instr_fl;
371 }
372
373 static int cmp_attr_arm_SymConst(ir_node *a, ir_node *b)
374 {
375         const arm_SymConst_attr_t *attr_a;
376         const arm_SymConst_attr_t *attr_b;
377
378         if (cmp_attr_arm(a, b))
379                 return 1;
380
381         attr_a = get_irn_generic_attr_const(a);
382         attr_b = get_irn_generic_attr_const(b);
383         return attr_a->entity != attr_b->entity
384                 || attr_a->fp_offset != attr_b->fp_offset;
385 }
386
387 static int cmp_attr_arm_CopyB(ir_node *a, ir_node *b)
388 {
389         const arm_CopyB_attr_t *attr_a;
390         const arm_CopyB_attr_t *attr_b;
391
392         if (cmp_attr_arm(a, b))
393                 return 1;
394
395         attr_a = get_irn_generic_attr_const(a);
396         attr_b = get_irn_generic_attr_const(b);
397         return attr_a->size != attr_b->size;
398 }
399
400 static int cmp_attr_arm_CondJmp(ir_node *a, ir_node *b)
401 {
402         (void) a;
403         (void) b;
404         /* never identical */
405         return 1;
406 }
407
408 static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b)
409 {
410         (void) a;
411         (void) b;
412         /* never identical */
413         return 1;
414 }
415
416 static int cmp_attr_arm_fpaConst(ir_node *a, ir_node *b)
417 {
418         const arm_fpaConst_attr_t *attr_a;
419         const arm_fpaConst_attr_t *attr_b;
420
421         if (cmp_attr_arm(a, b))
422                 return 1;
423
424         attr_a = get_arm_fpaConst_attr_const(a);
425         attr_b = get_arm_fpaConst_attr_const(b);
426
427         return attr_a->tv != attr_b->tv;
428 }
429
430
431 arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node)
432 {
433         return (arm_load_store_attr_t*) get_irn_generic_attr(node);
434 }
435
436 const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node)
437 {
438         return (const arm_load_store_attr_t*) get_irn_generic_attr_const(node);
439 }
440
441 arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node)
442 {
443         return (arm_shifter_operand_t*) get_irn_generic_attr(node);
444 }
445
446 static int cmp_attr_arm_load_store(ir_node *a, ir_node *b)
447 {
448         const arm_load_store_attr_t *attr_a;
449         const arm_load_store_attr_t *attr_b;
450
451         if (cmp_attr_arm(a, b))
452                 return 1;
453
454         attr_a = get_arm_load_store_attr(a);
455         attr_b = get_arm_load_store_attr(b);
456         if (attr_a->entity != attr_b->entity
457                         || attr_a->entity_sign != attr_b->entity_sign
458                         || attr_a->offset != attr_b->offset)
459                 return 1;
460
461         return 0;
462 }
463
464 static int cmp_attr_arm_shifter_operand(ir_node *a, ir_node *b)
465 {
466         const arm_shifter_operand_t *attr_a;
467         const arm_shifter_operand_t *attr_b;
468
469         if (cmp_attr_arm(a, b))
470                 return 1;
471
472         attr_a = get_arm_shifter_operand_attr(a);
473         attr_b = get_arm_shifter_operand_attr(b);
474         if (attr_a->shift_modifier != attr_b->shift_modifier
475                         || attr_a->immediate_value != attr_b->immediate_value
476                         || attr_a->shift_immediate != attr_b->shift_immediate)
477                 return 1;
478
479         return 0;
480 }
481
482 static int cmp_attr_arm_cmp(ir_node *a, ir_node *b)
483 {
484         const arm_cmp_attr_t *attr_a;
485         const arm_cmp_attr_t *attr_b;
486
487         if (cmp_attr_arm(a, b))
488                 return 1;
489
490         attr_a = get_irn_generic_attr_const(a);
491         attr_b = get_irn_generic_attr_const(b);
492         if (attr_a->ins_permuted != attr_b->ins_permuted
493                         || attr_a->is_unsigned != attr_b->is_unsigned)
494                 return 1;
495         return 0;
496 }
497
498 /** copies the ARM attributes of a node. */
499 static void arm_copy_attr(ir_graph *irg, const ir_node *old_node,
500                           ir_node *new_node)
501 {
502         struct obstack   *obst    = get_irg_obstack(irg);
503         const arm_attr_t *attr_old = get_arm_attr_const(old_node);
504         arm_attr_t       *attr_new = get_arm_attr(new_node);
505         backend_info_t   *old_info = be_get_info(old_node);
506         backend_info_t   *new_info = be_get_info(new_node);
507
508         /* copy the attributes */
509         memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
510
511         /* copy out flags */
512         new_info->out_infos =
513                 DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
514 }
515
516
517
518 /* Include the generated constructor functions */
519 #include "gen_arm_new_nodes.c.inl"