2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
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.
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.
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
22 * @brief This file implements the creation of the architecture specific firm
23 * opcodes and the corresponding node constructors for the arm
25 * @author Oliver Richter, Tobias Gneist
34 #include "irgraph_t.h"
44 #include "../bearch.h"
46 #include "arm_nodes_attr.h"
47 #include "arm_new_nodes.h"
48 #include "arm_optimize.h"
51 #include "bearch_arm_t.h"
53 const char *arm_get_fpa_imm_name(long imm_value)
55 static const char *fpa_imm[] = {
65 return fpa_imm[imm_value];
68 static bool arm_has_symconst_attr(const ir_node *node)
70 return is_arm_SymConst(node) || is_arm_FrameAddr(node) || is_arm_Bl(node);
73 static bool has_load_store_attr(const ir_node *node)
75 return is_arm_Ldr(node) || is_arm_Str(node) || is_arm_LinkLdrPC(node)
76 || is_arm_Ldf(node) || is_arm_Stf(node);
79 static bool has_shifter_operand(const ir_node *node)
81 return is_arm_Add(node) || is_arm_And(node) || is_arm_Or(node)
82 || is_arm_Eor(node) || is_arm_Bic(node) || is_arm_Sub(node)
83 || is_arm_Rsb(node) || is_arm_Mov(node) || is_arm_Mvn(node)
84 || is_arm_Cmp(node) || is_arm_Tst(node) || is_arm_LinkMovPC(node);
87 static bool has_cmp_attr(const ir_node *node)
89 return is_arm_Cmp(node) || is_arm_Tst(node);
92 static bool has_farith_attr(const ir_node *node)
94 return is_arm_Adf(node) || is_arm_Muf(node) || is_arm_Suf(node)
95 || is_arm_Dvf(node) || is_arm_Mvf(node) || is_arm_FltX(node);
99 * Dumper interface for dumping arm nodes in vcg.
100 * @param F the output file
101 * @param n the node to dump
102 * @param reason indicates which kind of information should be dumped
104 static void arm_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
107 case dump_node_opcode_txt:
108 fprintf(F, "%s", get_irn_opname(n));
110 if (arm_has_symconst_attr(n)) {
111 const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
112 if (attr->entity != NULL) {
114 fputs(get_entity_name(attr->entity), F);
119 case dump_node_mode_txt:
120 /* mode isn't relevant in the backend */
123 case dump_node_nodeattr_txt:
124 /* TODO: dump shift modifiers */
127 case dump_node_info_txt:
128 arch_dump_reqs_and_registers(F, n);
130 if (has_load_store_attr(n)) {
131 const arm_load_store_attr_t *attr
132 = get_arm_load_store_attr_const(n);
133 ir_fprintf(F, "load_store_mode = %+F\n", attr->load_store_mode);
134 ir_fprintf(F, "entity = %+F\n", attr->entity);
135 fprintf(F, "offset = %ld\n", attr->offset);
136 fprintf(F, "is_frame_entity = %s\n",
137 attr->is_frame_entity ? "yes" : "no");
138 fprintf(F, "entity_sign = %s\n",
139 attr->entity_sign ? "yes" : "no");
141 if (has_shifter_operand(n)) {
142 const arm_shifter_operand_t *attr
143 = get_arm_shifter_operand_attr_const(n);
144 switch (attr->shift_modifier) {
148 fprintf(F, "modifier = imm %d ror %d\n",
149 attr->immediate_value, attr->shift_immediate);
151 case ARM_SHF_ASR_IMM:
152 fprintf(F, "modifier = V >>s %d\n", attr->shift_immediate);
154 case ARM_SHF_ASR_REG:
155 fprintf(F, "modifier = V >>s R\n");
157 case ARM_SHF_LSL_IMM:
158 fprintf(F, "modifier = V << %d\n", attr->shift_immediate);
160 case ARM_SHF_LSL_REG:
161 fprintf(F, "modifier = V << R\n");
163 case ARM_SHF_LSR_IMM:
164 fprintf(F, "modifier = V >> %d\n", attr->shift_immediate);
166 case ARM_SHF_LSR_REG:
167 fprintf(F, "modifier = V >> R\n");
169 case ARM_SHF_ROR_IMM:
170 fprintf(F, "modifier = V ROR %d\n", attr->shift_immediate);
172 case ARM_SHF_ROR_REG:
173 fprintf(F, "modifier = V ROR R\n");
176 fprintf(F, "modifier = RRX\n");
179 case ARM_SHF_INVALID:
180 fprintf(F, "modifier = INVALID SHIFT MODIFIER\n");
184 if (has_cmp_attr(n)) {
185 const arm_cmp_attr_t *attr = get_arm_cmp_attr_const(n);
186 fprintf(F, "cmp_attr =");
187 if (attr->is_unsigned) {
188 fprintf(F, " unsigned");
190 if (attr->ins_permuted) {
191 fprintf(F, " inputs swapped");
195 if (arm_has_symconst_attr(n)) {
196 const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
198 fprintf(F, "entity = ");
199 if (attr->entity != NULL) {
200 fprintf(F, "'%s'", get_entity_name(attr->entity));
205 fprintf(F, "frame offset = %d\n", attr->fp_offset);
207 if (has_farith_attr(n)) {
208 const arm_farith_attr_t *attr = get_arm_farith_attr_const(n);
209 ir_fprintf(F, "arithmetic mode = %+F\n", attr->mode);
215 arm_attr_t *get_arm_attr(ir_node *node)
217 assert(is_arm_irn(node) && "need arm node to get attributes");
218 return get_irn_generic_attr(node);
221 const arm_attr_t *get_arm_attr_const(const ir_node *node)
223 assert(is_arm_irn(node) && "need arm node to get attributes");
224 return get_irn_generic_attr_const(node);
227 static bool has_symconst_attr(const ir_node *node)
229 return is_arm_SymConst(node) || is_arm_FrameAddr(node) || is_arm_Bl(node);
232 arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node)
234 assert(has_symconst_attr(node));
235 return get_irn_generic_attr(node);
238 const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node)
240 assert(has_symconst_attr(node));
241 return get_irn_generic_attr_const(node);
244 static const arm_fConst_attr_t *get_arm_fConst_attr_const(const ir_node *node)
246 assert(is_arm_fConst(node));
247 return get_irn_generic_attr_const(node);
250 static arm_fConst_attr_t *get_arm_fConst_attr(ir_node *node)
252 assert(is_arm_fConst(node));
253 return get_irn_generic_attr(node);
256 arm_farith_attr_t *get_arm_farith_attr(ir_node *node)
258 assert(has_farith_attr(node));
259 return get_irn_generic_attr(node);
262 const arm_farith_attr_t *get_arm_farith_attr_const(const ir_node *node)
264 assert(has_farith_attr(node));
265 return get_irn_generic_attr_const(node);
268 arm_CondJmp_attr_t *get_arm_CondJmp_attr(ir_node *node)
270 assert(is_arm_B(node));
271 return get_irn_generic_attr(node);
274 const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node)
276 assert(is_arm_B(node));
277 return get_irn_generic_attr_const(node);
280 arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr(ir_node *node)
282 assert(is_arm_SwitchJmp(node));
283 return get_irn_generic_attr(node);
286 const arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr_const(const ir_node *node)
288 assert(is_arm_SwitchJmp(node));
289 return get_irn_generic_attr_const(node);
292 void set_arm_in_req_all(ir_node *node, const arch_register_req_t **reqs)
294 arm_attr_t *attr = get_arm_attr(node);
298 const arch_register_req_t *get_arm_in_req(const ir_node *node, int pos)
300 const arm_attr_t *attr = get_arm_attr_const(node);
301 return attr->in_req[pos];
304 void set_arm_req_in(ir_node *node, const arch_register_req_t *req, int pos)
306 arm_attr_t *attr = get_arm_attr(node);
307 attr->in_req[pos] = req;
310 tarval *get_fConst_value(const ir_node *node)
312 const arm_fConst_attr_t *attr = get_arm_fConst_attr_const(node);
316 void set_fConst_value(ir_node *node, tarval *tv)
318 arm_fConst_attr_t *attr = get_arm_fConst_attr(node);
322 pn_Cmp get_arm_CondJmp_pnc(const ir_node *node)
324 const arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr_const(node);
328 void set_arm_CondJmp_pnc(ir_node *node, pn_Cmp pnc)
330 arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr(node);
334 int get_arm_SwitchJmp_n_projs(const ir_node *node)
336 const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
337 return attr->n_projs;
340 void set_arm_SwitchJmp_n_projs(ir_node *node, int n_projs)
342 arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
343 attr->n_projs = n_projs;
346 long get_arm_SwitchJmp_default_proj_num(const ir_node *node)
348 const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
349 return attr->default_proj_num;
352 void set_arm_SwitchJmp_default_proj_num(ir_node *node, long default_proj_num)
354 arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
355 attr->default_proj_num = default_proj_num;
358 /* Set the ARM machine node attributes to default values. */
359 static void init_arm_attributes(ir_node *node, int flags,
360 const arch_register_req_t ** in_reqs,
361 const be_execution_unit_t ***execution_units,
364 ir_graph *irg = get_irn_irg(node);
365 struct obstack *obst = get_irg_obstack(irg);
366 arm_attr_t *attr = get_arm_attr(node);
367 backend_info_t *info;
368 (void) execution_units;
370 arch_irn_set_flags(node, flags);
371 attr->in_req = in_reqs;
372 attr->is_load_store = false;
374 info = be_get_info(node);
375 info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
376 memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
379 static void init_arm_load_store_attributes(ir_node *res, ir_mode *ls_mode,
381 int entity_sign, long offset,
382 bool is_frame_entity)
384 arm_load_store_attr_t *attr = get_irn_generic_attr(res);
385 attr->load_store_mode = ls_mode;
386 attr->entity = entity;
387 attr->entity_sign = entity_sign;
388 attr->is_frame_entity = is_frame_entity;
389 attr->offset = offset;
390 attr->base.is_load_store = true;
393 static void init_arm_shifter_operand(ir_node *res, unsigned immediate_value,
394 arm_shift_modifier_t shift_modifier,
395 unsigned shift_immediate)
397 arm_shifter_operand_t *attr = get_irn_generic_attr(res);
398 attr->immediate_value = immediate_value;
399 attr->shift_modifier = shift_modifier;
400 attr->shift_immediate = shift_immediate;
403 static void init_arm_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
405 arm_cmp_attr_t *attr = get_irn_generic_attr(res);
406 attr->ins_permuted = ins_permuted;
407 attr->is_unsigned = is_unsigned;
410 static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity,
413 arm_SymConst_attr_t *attr = get_irn_generic_attr(res);
414 attr->entity = entity;
415 attr->fp_offset = symconst_offset;
418 static void init_arm_farith_attributes(ir_node *res, ir_mode *mode)
420 arm_farith_attr_t *attr = get_irn_generic_attr(res);
424 static void init_arm_CopyB_attributes(ir_node *res, unsigned size)
426 arm_CopyB_attr_t *attr = get_irn_generic_attr(res);
430 static int cmp_attr_arm(ir_node *a, ir_node *b)
437 static int cmp_attr_arm_SymConst(ir_node *a, ir_node *b)
439 const arm_SymConst_attr_t *attr_a;
440 const arm_SymConst_attr_t *attr_b;
442 if (cmp_attr_arm(a, b))
445 attr_a = get_irn_generic_attr_const(a);
446 attr_b = get_irn_generic_attr_const(b);
447 return attr_a->entity != attr_b->entity
448 || attr_a->fp_offset != attr_b->fp_offset;
451 static int cmp_attr_arm_CopyB(ir_node *a, ir_node *b)
453 const arm_CopyB_attr_t *attr_a;
454 const arm_CopyB_attr_t *attr_b;
456 if (cmp_attr_arm(a, b))
459 attr_a = get_irn_generic_attr_const(a);
460 attr_b = get_irn_generic_attr_const(b);
461 return attr_a->size != attr_b->size;
464 static int cmp_attr_arm_CondJmp(ir_node *a, ir_node *b)
468 /* never identical */
472 static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b)
476 /* never identical */
480 static int cmp_attr_arm_fConst(ir_node *a, ir_node *b)
482 const arm_fConst_attr_t *attr_a;
483 const arm_fConst_attr_t *attr_b;
485 if (cmp_attr_arm(a, b))
488 attr_a = get_arm_fConst_attr_const(a);
489 attr_b = get_arm_fConst_attr_const(b);
491 return attr_a->tv != attr_b->tv;
495 arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node)
497 return (arm_load_store_attr_t*) get_irn_generic_attr(node);
500 const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node)
502 return (const arm_load_store_attr_t*) get_irn_generic_attr_const(node);
505 arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node)
507 return (arm_shifter_operand_t*) get_irn_generic_attr(node);
510 const arm_shifter_operand_t *get_arm_shifter_operand_attr_const(
513 return (const arm_shifter_operand_t*) get_irn_generic_attr_const(node);
516 arm_cmp_attr_t *get_arm_cmp_attr(ir_node *node)
518 return (arm_cmp_attr_t*) get_irn_generic_attr(node);
521 const arm_cmp_attr_t *get_arm_cmp_attr_const(const ir_node *node)
523 return (const arm_cmp_attr_t*) get_irn_generic_attr_const(node);
526 static int cmp_attr_arm_load_store(ir_node *a, ir_node *b)
528 const arm_load_store_attr_t *attr_a;
529 const arm_load_store_attr_t *attr_b;
531 if (cmp_attr_arm(a, b))
534 attr_a = get_arm_load_store_attr(a);
535 attr_b = get_arm_load_store_attr(b);
536 if (attr_a->entity != attr_b->entity
537 || attr_a->entity_sign != attr_b->entity_sign
538 || attr_a->offset != attr_b->offset)
544 static int cmp_attr_arm_shifter_operand(ir_node *a, ir_node *b)
546 const arm_shifter_operand_t *attr_a;
547 const arm_shifter_operand_t *attr_b;
549 if (cmp_attr_arm(a, b))
552 attr_a = get_arm_shifter_operand_attr(a);
553 attr_b = get_arm_shifter_operand_attr(b);
554 if (attr_a->shift_modifier != attr_b->shift_modifier
555 || attr_a->immediate_value != attr_b->immediate_value
556 || attr_a->shift_immediate != attr_b->shift_immediate)
562 static int cmp_attr_arm_cmp(ir_node *a, ir_node *b)
564 const arm_cmp_attr_t *attr_a;
565 const arm_cmp_attr_t *attr_b;
567 if (cmp_attr_arm(a, b))
570 attr_a = get_irn_generic_attr_const(a);
571 attr_b = get_irn_generic_attr_const(b);
572 if (attr_a->ins_permuted != attr_b->ins_permuted
573 || attr_a->is_unsigned != attr_b->is_unsigned)
578 static int cmp_attr_arm_farith(ir_node *a, ir_node *b)
580 const arm_farith_attr_t *attr_a;
581 const arm_farith_attr_t *attr_b;
583 if (cmp_attr_arm(a, b))
586 attr_a = get_arm_farith_attr_const(a);
587 attr_b = get_arm_farith_attr_const(b);
588 return attr_a->mode != attr_b->mode;
591 /** copies the ARM attributes of a node. */
592 static void arm_copy_attr(ir_graph *irg, const ir_node *old_node,
595 struct obstack *obst = get_irg_obstack(irg);
596 const arm_attr_t *attr_old = get_arm_attr_const(old_node);
597 arm_attr_t *attr_new = get_arm_attr(new_node);
598 backend_info_t *old_info = be_get_info(old_node);
599 backend_info_t *new_info = be_get_info(new_node);
601 /* copy the attributes */
602 memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
605 new_info->out_infos =
606 DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
610 /* Include the generated constructor functions */
611 #include "gen_arm_new_nodes.c.inl"