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