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);
78 static bool has_shifter_operand(const ir_node *node)
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) || is_arm_LinkMovPC(node);
86 static bool has_cmp_attr(const ir_node *node)
88 return is_arm_Cmp(node) || is_arm_Tst(node);
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
97 static void arm_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
100 case dump_node_opcode_txt:
101 fprintf(F, "%s", get_irn_opname(n));
103 if (arm_has_symconst_attr(n)) {
104 const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
105 if (attr->entity != NULL) {
107 fputs(get_entity_name(attr->entity), F);
112 case dump_node_mode_txt:
113 /* mode isn't relevant in the backend */
116 case dump_node_nodeattr_txt:
117 /* TODO: dump shift modifiers */
120 case dump_node_info_txt:
121 arch_dump_reqs_and_registers(F, n);
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");
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) {
141 fprintf(F, "modifier = imm %d ror %d\n",
142 attr->immediate_value, attr->shift_immediate);
144 case ARM_SHF_ASR_IMM:
145 fprintf(F, "modifier = V >>s %d\n", attr->shift_immediate);
147 case ARM_SHF_ASR_REG:
148 fprintf(F, "modifier = V >>s R\n");
150 case ARM_SHF_LSL_IMM:
151 fprintf(F, "modifier = V << %d\n", attr->shift_immediate);
153 case ARM_SHF_LSL_REG:
154 fprintf(F, "modifier = V << R\n");
156 case ARM_SHF_LSR_IMM:
157 fprintf(F, "modifier = V >> %d\n", attr->shift_immediate);
159 case ARM_SHF_LSR_REG:
160 fprintf(F, "modifier = V >> R\n");
162 case ARM_SHF_ROR_IMM:
163 fprintf(F, "modifier = V ROR %d\n", attr->shift_immediate);
165 case ARM_SHF_ROR_REG:
166 fprintf(F, "modifier = V ROR R\n");
169 fprintf(F, "modifier = RRX\n");
172 case ARM_SHF_INVALID:
173 fprintf(F, "modifier = INVALID SHIFT MODIFIER\n");
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");
183 if (attr->ins_permuted) {
184 fprintf(F, " inputs swapped");
188 if (arm_has_symconst_attr(n)) {
189 const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
191 fprintf(F, "entity = ");
192 if (attr->entity != NULL) {
193 fprintf(F, "'%s'", get_entity_name(attr->entity));
198 fprintf(F, "frame offset = %d\n", attr->fp_offset);
204 arm_attr_t *get_arm_attr(ir_node *node)
206 assert(is_arm_irn(node) && "need arm node to get attributes");
207 return get_irn_generic_attr(node);
210 const arm_attr_t *get_arm_attr_const(const ir_node *node)
212 assert(is_arm_irn(node) && "need arm node to get attributes");
213 return get_irn_generic_attr_const(node);
216 static bool has_symconst_attr(const ir_node *node)
218 return is_arm_SymConst(node) || is_arm_FrameAddr(node) || is_arm_Bl(node);
221 arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node)
223 assert(has_symconst_attr(node));
224 return get_irn_generic_attr(node);
227 const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node)
229 assert(has_symconst_attr(node));
230 return get_irn_generic_attr_const(node);
233 static const arm_fpaConst_attr_t *get_arm_fpaConst_attr_const(
236 const arm_attr_t *attr = get_arm_attr_const(node);
237 const arm_fpaConst_attr_t *fpa_attr = CONST_CAST_ARM_ATTR(arm_fpaConst_attr_t, attr);
242 static arm_fpaConst_attr_t *get_arm_fpaConst_attr(ir_node *node)
244 arm_attr_t *attr = get_arm_attr(node);
245 arm_fpaConst_attr_t *fpa_attr = CAST_ARM_ATTR(arm_fpaConst_attr_t, attr);
250 arm_CondJmp_attr_t *get_arm_CondJmp_attr(ir_node *node)
252 assert(is_arm_B(node));
253 return get_irn_generic_attr(node);
256 const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node)
258 assert(is_arm_B(node));
259 return get_irn_generic_attr_const(node);
262 arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr(ir_node *node)
264 assert(is_arm_SwitchJmp(node));
265 return get_irn_generic_attr(node);
268 const arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr_const(const ir_node *node)
270 assert(is_arm_SwitchJmp(node));
271 return get_irn_generic_attr_const(node);
274 void set_arm_in_req_all(ir_node *node, const arch_register_req_t **reqs)
276 arm_attr_t *attr = get_arm_attr(node);
280 const arch_register_req_t *get_arm_in_req(const ir_node *node, int pos)
282 const arm_attr_t *attr = get_arm_attr_const(node);
283 return attr->in_req[pos];
286 void set_arm_req_in(ir_node *node, const arch_register_req_t *req, int pos)
288 arm_attr_t *attr = get_arm_attr(node);
289 attr->in_req[pos] = req;
292 tarval *get_fpaConst_value(const ir_node *node)
294 const arm_fpaConst_attr_t *attr = get_arm_fpaConst_attr_const(node);
298 void set_fpaConst_value(ir_node *node, tarval *tv)
300 arm_fpaConst_attr_t *attr = get_arm_fpaConst_attr(node);
304 pn_Cmp get_arm_CondJmp_pnc(const ir_node *node)
306 const arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr_const(node);
310 void set_arm_CondJmp_pnc(ir_node *node, pn_Cmp pnc)
312 arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr(node);
316 int get_arm_SwitchJmp_n_projs(const ir_node *node)
318 const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
319 return attr->n_projs;
322 void set_arm_SwitchJmp_n_projs(ir_node *node, int n_projs)
324 arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
325 attr->n_projs = n_projs;
328 long get_arm_SwitchJmp_default_proj_num(const ir_node *node)
330 const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
331 return attr->default_proj_num;
334 void set_arm_SwitchJmp_default_proj_num(ir_node *node, long default_proj_num)
336 arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
337 attr->default_proj_num = default_proj_num;
340 /* Set the ARM machine node attributes to default values. */
341 static void init_arm_attributes(ir_node *node, int flags,
342 const arch_register_req_t ** in_reqs,
343 const be_execution_unit_t ***execution_units,
346 ir_graph *irg = get_irn_irg(node);
347 struct obstack *obst = get_irg_obstack(irg);
348 arm_attr_t *attr = get_arm_attr(node);
349 backend_info_t *info;
350 (void) execution_units;
352 arch_irn_set_flags(node, flags);
353 attr->in_req = in_reqs;
356 info = be_get_info(node);
357 info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
358 memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
361 static void init_arm_load_store_attributes(ir_node *res, ir_mode *ls_mode,
363 int entity_sign, long offset,
364 bool is_frame_entity)
366 arm_load_store_attr_t *attr = get_irn_generic_attr(res);
367 attr->load_store_mode = ls_mode;
368 attr->entity = entity;
369 attr->entity_sign = entity_sign;
370 attr->is_frame_entity = is_frame_entity;
371 attr->offset = offset;
372 attr->base.is_load_store = true;
375 static void init_arm_shifter_operand(ir_node *res, unsigned immediate_value,
376 arm_shift_modifier_t shift_modifier,
377 unsigned shift_immediate)
379 arm_shifter_operand_t *attr = get_irn_generic_attr(res);
380 attr->immediate_value = immediate_value;
381 attr->shift_modifier = shift_modifier;
382 attr->shift_immediate = shift_immediate;
385 static void init_arm_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
387 arm_cmp_attr_t *attr = get_irn_generic_attr(res);
388 attr->ins_permuted = ins_permuted;
389 attr->is_unsigned = is_unsigned;
392 static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity,
395 arm_SymConst_attr_t *attr = get_irn_generic_attr(res);
396 attr->entity = entity;
397 attr->fp_offset = symconst_offset;
400 static void init_arm_CopyB_attributes(ir_node *res, unsigned size)
402 arm_CopyB_attr_t *attr = get_irn_generic_attr(res);
406 static int cmp_attr_arm(ir_node *a, ir_node *b)
408 arm_attr_t *attr_a = get_irn_generic_attr(a);
409 arm_attr_t *attr_b = get_irn_generic_attr(b);
410 return attr_a->instr_fl != attr_b->instr_fl;
413 static int cmp_attr_arm_SymConst(ir_node *a, ir_node *b)
415 const arm_SymConst_attr_t *attr_a;
416 const arm_SymConst_attr_t *attr_b;
418 if (cmp_attr_arm(a, b))
421 attr_a = get_irn_generic_attr_const(a);
422 attr_b = get_irn_generic_attr_const(b);
423 return attr_a->entity != attr_b->entity
424 || attr_a->fp_offset != attr_b->fp_offset;
427 static int cmp_attr_arm_CopyB(ir_node *a, ir_node *b)
429 const arm_CopyB_attr_t *attr_a;
430 const arm_CopyB_attr_t *attr_b;
432 if (cmp_attr_arm(a, b))
435 attr_a = get_irn_generic_attr_const(a);
436 attr_b = get_irn_generic_attr_const(b);
437 return attr_a->size != attr_b->size;
440 static int cmp_attr_arm_CondJmp(ir_node *a, ir_node *b)
444 /* never identical */
448 static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b)
452 /* never identical */
456 static int cmp_attr_arm_fpaConst(ir_node *a, ir_node *b)
458 const arm_fpaConst_attr_t *attr_a;
459 const arm_fpaConst_attr_t *attr_b;
461 if (cmp_attr_arm(a, b))
464 attr_a = get_arm_fpaConst_attr_const(a);
465 attr_b = get_arm_fpaConst_attr_const(b);
467 return attr_a->tv != attr_b->tv;
471 arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node)
473 return (arm_load_store_attr_t*) get_irn_generic_attr(node);
476 const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node)
478 return (const arm_load_store_attr_t*) get_irn_generic_attr_const(node);
481 arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node)
483 return (arm_shifter_operand_t*) get_irn_generic_attr(node);
486 const arm_shifter_operand_t *get_arm_shifter_operand_attr_const(
489 return (const arm_shifter_operand_t*) get_irn_generic_attr_const(node);
492 arm_cmp_attr_t *get_arm_cmp_attr(ir_node *node)
494 return (arm_cmp_attr_t*) get_irn_generic_attr(node);
497 const arm_cmp_attr_t *get_arm_cmp_attr_const(const ir_node *node)
499 return (const arm_cmp_attr_t*) get_irn_generic_attr_const(node);
502 static int cmp_attr_arm_load_store(ir_node *a, ir_node *b)
504 const arm_load_store_attr_t *attr_a;
505 const arm_load_store_attr_t *attr_b;
507 if (cmp_attr_arm(a, b))
510 attr_a = get_arm_load_store_attr(a);
511 attr_b = get_arm_load_store_attr(b);
512 if (attr_a->entity != attr_b->entity
513 || attr_a->entity_sign != attr_b->entity_sign
514 || attr_a->offset != attr_b->offset)
520 static int cmp_attr_arm_shifter_operand(ir_node *a, ir_node *b)
522 const arm_shifter_operand_t *attr_a;
523 const arm_shifter_operand_t *attr_b;
525 if (cmp_attr_arm(a, b))
528 attr_a = get_arm_shifter_operand_attr(a);
529 attr_b = get_arm_shifter_operand_attr(b);
530 if (attr_a->shift_modifier != attr_b->shift_modifier
531 || attr_a->immediate_value != attr_b->immediate_value
532 || attr_a->shift_immediate != attr_b->shift_immediate)
538 static int cmp_attr_arm_cmp(ir_node *a, ir_node *b)
540 const arm_cmp_attr_t *attr_a;
541 const arm_cmp_attr_t *attr_b;
543 if (cmp_attr_arm(a, b))
546 attr_a = get_irn_generic_attr_const(a);
547 attr_b = get_irn_generic_attr_const(b);
548 if (attr_a->ins_permuted != attr_b->ins_permuted
549 || attr_a->is_unsigned != attr_b->is_unsigned)
554 /** copies the ARM attributes of a node. */
555 static void arm_copy_attr(ir_graph *irg, const ir_node *old_node,
558 struct obstack *obst = get_irg_obstack(irg);
559 const arm_attr_t *attr_old = get_arm_attr_const(old_node);
560 arm_attr_t *attr_new = get_arm_attr(new_node);
561 backend_info_t *old_info = be_get_info(old_node);
562 backend_info_t *new_info = be_get_info(new_node);
564 /* copy the attributes */
565 memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
568 new_info->out_infos =
569 DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
573 /* Include the generated constructor functions */
574 #include "gen_arm_new_nodes.c.inl"