2 * Copyright (C) 1995-2011 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
33 #include "irgraph_t.h"
44 #include "arm_nodes_attr.h"
45 #include "arm_new_nodes.h"
46 #include "arm_optimize.h"
49 #include "bearch_arm_t.h"
51 const char *arm_get_fpa_imm_name(long imm_value)
53 static const char *fpa_imm[] = {
63 return fpa_imm[imm_value];
66 static bool arm_has_symconst_attr(const ir_node *node)
68 return is_arm_SymConst(node) || is_arm_FrameAddr(node) || is_arm_Bl(node);
71 static bool has_load_store_attr(const ir_node *node)
73 return is_arm_Ldr(node) || is_arm_Str(node) || is_arm_LinkLdrPC(node)
74 || is_arm_Ldf(node) || is_arm_Stf(node);
77 static bool has_shifter_operand(const ir_node *node)
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);
85 static bool has_cmp_attr(const ir_node *node)
87 return is_arm_Cmp(node) || is_arm_Tst(node);
90 static bool has_farith_attr(const ir_node *node)
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);
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
102 static void arm_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
105 case dump_node_opcode_txt:
106 fprintf(F, "%s", get_irn_opname(n));
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) {
112 fputs(get_entity_name(attr->entity), F);
117 case dump_node_mode_txt:
118 /* mode isn't relevant in the backend */
121 case dump_node_nodeattr_txt:
122 /* TODO: dump shift modifiers */
125 case dump_node_info_txt:
126 arch_dump_reqs_and_registers(F, n);
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");
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) {
146 fprintf(F, "modifier = imm %d ror %d\n",
147 attr->immediate_value, attr->shift_immediate);
149 case ARM_SHF_ASR_IMM:
150 fprintf(F, "modifier = V >>s %d\n", attr->shift_immediate);
152 case ARM_SHF_ASR_REG:
153 fprintf(F, "modifier = V >>s R\n");
155 case ARM_SHF_LSL_IMM:
156 fprintf(F, "modifier = V << %d\n", attr->shift_immediate);
158 case ARM_SHF_LSL_REG:
159 fprintf(F, "modifier = V << R\n");
161 case ARM_SHF_LSR_IMM:
162 fprintf(F, "modifier = V >> %d\n", attr->shift_immediate);
164 case ARM_SHF_LSR_REG:
165 fprintf(F, "modifier = V >> R\n");
167 case ARM_SHF_ROR_IMM:
168 fprintf(F, "modifier = V ROR %d\n", attr->shift_immediate);
170 case ARM_SHF_ROR_REG:
171 fprintf(F, "modifier = V ROR R\n");
174 fprintf(F, "modifier = RRX\n");
177 case ARM_SHF_INVALID:
178 fprintf(F, "modifier = INVALID SHIFT MODIFIER\n");
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");
188 if (attr->ins_permuted) {
189 fprintf(F, " inputs swapped");
193 if (arm_has_symconst_attr(n)) {
194 const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
196 fprintf(F, "entity = ");
197 if (attr->entity != NULL) {
198 fprintf(F, "'%s'", get_entity_name(attr->entity));
203 fprintf(F, "frame offset = %d\n", attr->fp_offset);
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);
213 arm_attr_t *get_arm_attr(ir_node *node)
215 assert(is_arm_irn(node) && "need arm node to get attributes");
216 return (arm_attr_t*)get_irn_generic_attr(node);
219 const arm_attr_t *get_arm_attr_const(const ir_node *node)
221 assert(is_arm_irn(node) && "need arm node to get attributes");
222 return (const arm_attr_t*)get_irn_generic_attr_const(node);
225 static bool has_symconst_attr(const ir_node *node)
227 return is_arm_SymConst(node) || is_arm_FrameAddr(node) || is_arm_Bl(node);
230 arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node)
232 assert(has_symconst_attr(node));
233 return (arm_SymConst_attr_t*)get_irn_generic_attr(node);
236 const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node)
238 assert(has_symconst_attr(node));
239 return (const arm_SymConst_attr_t*)get_irn_generic_attr_const(node);
242 static const arm_fConst_attr_t *get_arm_fConst_attr_const(const ir_node *node)
244 assert(is_arm_fConst(node));
245 return (const arm_fConst_attr_t*)get_irn_generic_attr_const(node);
248 static arm_fConst_attr_t *get_arm_fConst_attr(ir_node *node)
250 assert(is_arm_fConst(node));
251 return (arm_fConst_attr_t*)get_irn_generic_attr(node);
254 arm_farith_attr_t *get_arm_farith_attr(ir_node *node)
256 assert(has_farith_attr(node));
257 return (arm_farith_attr_t*)get_irn_generic_attr(node);
260 const arm_farith_attr_t *get_arm_farith_attr_const(const ir_node *node)
262 assert(has_farith_attr(node));
263 return (const arm_farith_attr_t*)get_irn_generic_attr_const(node);
266 arm_CondJmp_attr_t *get_arm_CondJmp_attr(ir_node *node)
268 assert(is_arm_B(node));
269 return (arm_CondJmp_attr_t*)get_irn_generic_attr(node);
272 const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node)
274 assert(is_arm_B(node));
275 return (const arm_CondJmp_attr_t*)get_irn_generic_attr_const(node);
278 arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr(ir_node *node)
280 assert(is_arm_SwitchJmp(node));
281 return (arm_SwitchJmp_attr_t*)get_irn_generic_attr(node);
284 const arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr_const(const ir_node *node)
286 assert(is_arm_SwitchJmp(node));
287 return (const arm_SwitchJmp_attr_t*)get_irn_generic_attr_const(node);
290 arm_CopyB_attr_t *get_arm_CopyB_attr(ir_node *node)
292 assert(is_arm_CopyB(node));
293 return (arm_CopyB_attr_t*)get_irn_generic_attr(node);
296 const arm_CopyB_attr_t *get_arm_CopyB_attr_const(const ir_node *node)
298 assert(is_arm_CopyB(node));
299 return (const arm_CopyB_attr_t*)get_irn_generic_attr_const(node);
302 ir_tarval *get_fConst_value(const ir_node *node)
304 const arm_fConst_attr_t *attr = get_arm_fConst_attr_const(node);
308 void set_fConst_value(ir_node *node, ir_tarval *tv)
310 arm_fConst_attr_t *attr = get_arm_fConst_attr(node);
314 ir_relation get_arm_CondJmp_relation(const ir_node *node)
316 const arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr_const(node);
317 return attr->relation;
320 void set_arm_CondJmp_relation(ir_node *node, ir_relation relation)
322 arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr(node);
323 attr->relation = relation;
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,
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;
338 arch_set_irn_flags(node, flags);
339 arch_set_irn_register_reqs_in(node, in_reqs);
340 attr->is_load_store = false;
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]));
347 static void init_arm_load_store_attributes(ir_node *res, ir_mode *ls_mode,
349 int entity_sign, long offset,
350 bool is_frame_entity)
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;
361 static void init_arm_shifter_operand(ir_node *res, unsigned immediate_value,
362 arm_shift_modifier_t shift_modifier,
363 unsigned shift_immediate)
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;
371 static void init_arm_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
373 arm_cmp_attr_t *attr = get_arm_cmp_attr(res);
374 attr->ins_permuted = ins_permuted;
375 attr->is_unsigned = is_unsigned;
378 static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity,
381 arm_SymConst_attr_t *attr = get_arm_SymConst_attr(res);
382 attr->entity = entity;
383 attr->fp_offset = symconst_offset;
386 static void init_arm_farith_attributes(ir_node *res, ir_mode *mode)
388 arm_farith_attr_t *attr = get_arm_farith_attr(res);
392 static void init_arm_CopyB_attributes(ir_node *res, unsigned size)
394 arm_CopyB_attr_t *attr = get_arm_CopyB_attr(res);
398 static void init_arm_SwitchJmp_attributes(ir_node *res,
399 const ir_switch_table *table)
401 unsigned n_outs = arch_get_irn_n_outs(res);
404 arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(res);
407 for (o = 0; o < n_outs; ++o) {
408 arch_set_irn_register_req_out(res, o, arch_no_register_req);
412 static int cmp_attr_arm(const ir_node *a, const ir_node *b)
419 static int cmp_attr_arm_SymConst(const ir_node *a, const ir_node *b)
421 const arm_SymConst_attr_t *attr_a;
422 const arm_SymConst_attr_t *attr_b;
424 if (cmp_attr_arm(a, b))
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;
433 static int cmp_attr_arm_CopyB(const ir_node *a, const ir_node *b)
435 const arm_CopyB_attr_t *attr_a;
436 const arm_CopyB_attr_t *attr_b;
438 if (cmp_attr_arm(a, b))
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;
446 static int cmp_attr_arm_CondJmp(const ir_node *a, const ir_node *b)
450 /* never identical */
454 static int cmp_attr_arm_SwitchJmp(const ir_node *a, const ir_node *b)
458 /* never identical */
462 static int cmp_attr_arm_fConst(const ir_node *a, const ir_node *b)
464 const arm_fConst_attr_t *attr_a;
465 const arm_fConst_attr_t *attr_b;
467 if (cmp_attr_arm(a, b))
470 attr_a = get_arm_fConst_attr_const(a);
471 attr_b = get_arm_fConst_attr_const(b);
473 return attr_a->tv != attr_b->tv;
477 arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node)
479 return (arm_load_store_attr_t*) get_irn_generic_attr(node);
482 const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node)
484 return (const arm_load_store_attr_t*) get_irn_generic_attr_const(node);
487 arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node)
489 return (arm_shifter_operand_t*) get_irn_generic_attr(node);
492 const arm_shifter_operand_t *get_arm_shifter_operand_attr_const(
495 return (const arm_shifter_operand_t*) get_irn_generic_attr_const(node);
498 arm_cmp_attr_t *get_arm_cmp_attr(ir_node *node)
500 return (arm_cmp_attr_t*) get_irn_generic_attr(node);
503 const arm_cmp_attr_t *get_arm_cmp_attr_const(const ir_node *node)
505 return (const arm_cmp_attr_t*) get_irn_generic_attr_const(node);
508 static int cmp_attr_arm_load_store(const ir_node *a, const ir_node *b)
510 const arm_load_store_attr_t *attr_a;
511 const arm_load_store_attr_t *attr_b;
513 if (cmp_attr_arm(a, b))
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)
526 static int cmp_attr_arm_shifter_operand(const ir_node *a, const ir_node *b)
528 const arm_shifter_operand_t *attr_a;
529 const arm_shifter_operand_t *attr_b;
531 if (cmp_attr_arm(a, b))
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)
544 static int cmp_attr_arm_cmp(const ir_node *a, const ir_node *b)
546 const arm_cmp_attr_t *attr_a;
547 const arm_cmp_attr_t *attr_b;
549 if (cmp_attr_arm(a, b))
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)
560 static int cmp_attr_arm_farith(const ir_node *a, const ir_node *b)
562 const arm_farith_attr_t *attr_a;
563 const arm_farith_attr_t *attr_b;
565 if (cmp_attr_arm(a, b))
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;
573 /** copies the ARM attributes of a node. */
574 static void arm_copy_attr(ir_graph *irg, const ir_node *old_node,
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);
583 /* copy the attributes */
584 memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
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;
594 /* Include the generated constructor functions */
595 #include "gen_arm_new_nodes.c.inl"