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
33 #include "irgraph_t.h"
43 #include "../bearch.h"
45 #include "arm_nodes_attr.h"
46 #include "arm_new_nodes.h"
47 #include "arm_optimize.h"
50 #include "bearch_arm_t.h"
53 * Return the fpa immediate from the encoding.
55 const char *arm_get_fpa_imm_name(long imm_value)
57 static const char *fpa_imm[] = {
67 return fpa_imm[imm_value];
72 * Dumper interface for dumping arm nodes in vcg.
73 * @param F the output file
74 * @param n the node to dump
75 * @param reason indicates which kind of information should be dumped
77 static void arm_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
80 //arm_attr_t *attr = get_arm_attr(n);
83 case dump_node_opcode_txt:
84 fprintf(F, "%s", get_irn_opname(n));
87 case dump_node_mode_txt:
88 mode = get_irn_mode(n);
91 fprintf(F, "[%s]", get_mode_name(mode));
94 fprintf(F, "[?NOMODE?]");
98 case dump_node_nodeattr_txt:
99 /* TODO: dump shift modifiers */
102 case dump_node_info_txt:
103 arch_dump_reqs_and_registers(F, n);
105 if (is_arm_CopyB(n)) {
106 //fprintf(F, "size = %lu\n", get_arm_imm_value(n));
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));
114 fprintf(F, "immediate value = %ld (0x%08lx)\n", v, v);
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));
129 /* Returns the attributes of a generic Arm node. */
130 arm_attr_t *get_arm_attr(ir_node *node)
132 assert(is_arm_irn(node) && "need arm node to get attributes");
133 return get_irn_generic_attr(node);
136 const arm_attr_t *get_arm_attr_const(const ir_node *node)
138 assert(is_arm_irn(node) && "need arm node to get attributes");
139 return get_irn_generic_attr_const(node);
143 * Returns the attributes of an ARM SymConst node.
145 arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node)
147 assert(is_arm_SymConst(node) || is_arm_FrameAddr(node));
148 return get_irn_generic_attr(node);
151 const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node)
153 assert(is_arm_SymConst(node) || is_arm_FrameAddr(node));
154 return get_irn_generic_attr_const(node);
157 static const arm_fpaConst_attr_t *get_arm_fpaConst_attr_const(const ir_node *node)
159 const arm_attr_t *attr = get_arm_attr_const(node);
160 const arm_fpaConst_attr_t *fpa_attr = CONST_CAST_ARM_ATTR(arm_fpaConst_attr_t, attr);
165 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);
173 /* Returns the attributes of a CondJmp node. */
174 arm_CondJmp_attr_t *get_arm_CondJmp_attr(ir_node *node)
176 assert(is_arm_B(node));
177 return get_irn_generic_attr(node);
180 const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node)
182 assert(is_arm_B(node));
183 return get_irn_generic_attr_const(node);
186 /* Returns the attributes of a SwitchJmp node. */
187 arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr(ir_node *node)
189 assert(is_arm_SwitchJmp(node));
190 return get_irn_generic_attr(node);
193 const arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr_const(const ir_node *node)
195 assert(is_arm_SwitchJmp(node));
196 return get_irn_generic_attr_const(node);
200 * Returns the argument register requirements of a arm node.
202 const arch_register_req_t **get_arm_in_req_all(const ir_node *node)
204 const arm_attr_t *attr = get_arm_attr_const(node);
209 * Returns the argument register requirement at position pos of an arm node.
211 const arch_register_req_t *get_arm_in_req(const ir_node *node, int pos)
213 const arm_attr_t *attr = get_arm_attr_const(node);
214 return attr->in_req[pos];
218 * Sets the IN register requirements at position pos.
220 void set_arm_req_in(ir_node *node, const arch_register_req_t *req, int pos)
222 arm_attr_t *attr = get_arm_attr(node);
223 attr->in_req[pos] = req;
227 * Returns the fpaConst value
229 tarval *get_fpaConst_value(const ir_node *node)
231 const arm_fpaConst_attr_t *attr = get_arm_fpaConst_attr_const(node);
236 * Sets the tarval value
238 void set_fpaConst_value(ir_node *node, tarval *tv)
240 arm_fpaConst_attr_t *attr = get_arm_fpaConst_attr(node);
245 * Returns the proj num
247 int get_arm_CondJmp_proj_num(const ir_node *node)
249 const arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr_const(node);
250 return attr->proj_num;
256 void set_arm_CondJmp_proj_num(ir_node *node, int proj_num)
258 arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr(node);
259 attr->proj_num = proj_num;
263 * Returns the number of projs of a SwitchJmp.
265 int get_arm_SwitchJmp_n_projs(const ir_node *node)
267 const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
268 return attr->n_projs;
272 * Sets the number of projs.
274 void set_arm_SwitchJmp_n_projs(ir_node *node, int n_projs)
276 arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
277 attr->n_projs = n_projs;
281 * Returns the default_proj_num.
283 long get_arm_SwitchJmp_default_proj_num(const ir_node *node)
285 const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
286 return attr->default_proj_num;
290 * Sets the default_proj_num.
292 void set_arm_SwitchJmp_default_proj_num(ir_node *node, long default_proj_num)
294 arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
295 attr->default_proj_num = default_proj_num;
298 /* Set the ARM machine node attributes to default values. */
299 static void init_arm_attributes(ir_node *node, int flags,
300 const arch_register_req_t ** in_reqs,
301 const be_execution_unit_t ***execution_units,
304 ir_graph *irg = get_irn_irg(node);
305 struct obstack *obst = get_irg_obstack(irg);
306 arm_attr_t *attr = get_arm_attr(node);
307 backend_info_t *info;
308 (void) execution_units;
310 arch_irn_set_flags(node, flags);
311 attr->in_req = in_reqs;
314 info = be_get_info(node);
315 info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
316 memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
319 static void init_arm_load_store_attributes(ir_node *res, ir_mode *ls_mode,
321 int entity_sign, long offset,
322 bool is_frame_entity)
324 arm_load_store_attr_t *attr = get_irn_generic_attr(res);
325 attr->load_store_mode = ls_mode;
326 attr->entity = entity;
327 attr->entity_sign = entity_sign;
328 attr->is_frame_entity = is_frame_entity;
329 attr->offset = offset;
330 attr->base.is_load_store = true;
333 static void init_arm_shifter_operand(ir_node *res, unsigned immediate_value,
334 arm_shift_modifier shift_modifier,
335 unsigned shift_immediate)
337 arm_shifter_operand_t *attr = get_irn_generic_attr(res);
338 attr->immediate_value = immediate_value;
339 attr->shift_modifier = shift_modifier;
340 attr->shift_immediate = shift_immediate;
343 static void init_arm_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
345 arm_cmp_attr_t *attr = get_irn_generic_attr(res);
346 attr->ins_permuted = ins_permuted;
347 attr->is_unsigned = is_unsigned;
350 static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity)
352 arm_SymConst_attr_t *attr = get_irn_generic_attr(res);
353 attr->entity = entity;
357 static void init_arm_CopyB_attributes(ir_node *res, unsigned size)
359 arm_CopyB_attr_t *attr = get_irn_generic_attr(res);
363 static int cmp_attr_arm(ir_node *a, ir_node *b)
365 arm_attr_t *attr_a = get_irn_generic_attr(a);
366 arm_attr_t *attr_b = get_irn_generic_attr(b);
367 return attr_a->instr_fl != attr_b->instr_fl;
370 static int cmp_attr_arm_SymConst(ir_node *a, ir_node *b)
372 const arm_SymConst_attr_t *attr_a;
373 const arm_SymConst_attr_t *attr_b;
375 if (cmp_attr_arm(a, b))
378 attr_a = get_irn_generic_attr_const(a);
379 attr_b = get_irn_generic_attr_const(b);
380 return attr_a->entity != attr_b->entity
381 || attr_a->fp_offset != attr_b->fp_offset;
384 static int cmp_attr_arm_CopyB(ir_node *a, ir_node *b)
386 const arm_CopyB_attr_t *attr_a;
387 const arm_CopyB_attr_t *attr_b;
389 if (cmp_attr_arm(a, b))
392 attr_a = get_irn_generic_attr_const(a);
393 attr_b = get_irn_generic_attr_const(b);
394 return attr_a->size != attr_b->size;
397 static int cmp_attr_arm_CondJmp(ir_node *a, ir_node *b)
401 /* never identical */
405 static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b)
409 /* never identical */
413 static int cmp_attr_arm_fpaConst(ir_node *a, ir_node *b)
415 const arm_fpaConst_attr_t *attr_a;
416 const arm_fpaConst_attr_t *attr_b;
418 if (cmp_attr_arm(a, b))
421 attr_a = get_arm_fpaConst_attr_const(a);
422 attr_b = get_arm_fpaConst_attr_const(b);
424 return attr_a->tv != attr_b->tv;
428 arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node)
430 return (arm_load_store_attr_t*) get_irn_generic_attr(node);
433 const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node)
435 return (const arm_load_store_attr_t*) get_irn_generic_attr_const(node);
438 arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node)
440 return (arm_shifter_operand_t*) get_irn_generic_attr(node);
443 static int cmp_attr_arm_load_store(ir_node *a, ir_node *b)
445 const arm_load_store_attr_t *attr_a;
446 const arm_load_store_attr_t *attr_b;
448 if (cmp_attr_arm(a, b))
451 attr_a = get_arm_load_store_attr(a);
452 attr_b = get_arm_load_store_attr(b);
453 if (attr_a->entity != attr_b->entity
454 || attr_a->entity_sign != attr_b->entity_sign
455 || attr_a->offset != attr_b->offset)
461 static int cmp_attr_arm_shifter_operand(ir_node *a, ir_node *b)
463 const arm_shifter_operand_t *attr_a;
464 const arm_shifter_operand_t *attr_b;
466 if (cmp_attr_arm(a, b))
469 attr_a = get_arm_shifter_operand_attr(a);
470 attr_b = get_arm_shifter_operand_attr(b);
471 if (attr_a->shift_modifier != attr_b->shift_modifier
472 || attr_a->immediate_value != attr_b->immediate_value
473 || attr_a->shift_immediate != attr_b->shift_immediate)
479 static int cmp_attr_arm_cmp(ir_node *a, ir_node *b)
481 const arm_cmp_attr_t *attr_a;
482 const arm_cmp_attr_t *attr_b;
484 if (cmp_attr_arm(a, b))
487 attr_a = get_irn_generic_attr_const(a);
488 attr_b = get_irn_generic_attr_const(b);
489 if (attr_a->ins_permuted != attr_b->ins_permuted
490 || attr_a->is_unsigned != attr_b->is_unsigned)
495 /** copies the ARM attributes of a node. */
496 static void arm_copy_attr(ir_graph *irg, const ir_node *old_node,
499 struct obstack *obst = get_irg_obstack(irg);
500 const arm_attr_t *attr_old = get_arm_attr_const(old_node);
501 arm_attr_t *attr_new = get_arm_attr(new_node);
502 backend_info_t *old_info = be_get_info(old_node);
503 backend_info_t *new_info = be_get_info(new_node);
505 /* copy the attributes */
506 memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
509 new_info->out_infos =
510 DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
515 /* Include the generated constructor functions */
516 #include "gen_arm_new_nodes.c.inl"