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) {
56 static const char *fpa_imm[] = {
66 return fpa_imm[imm_value];
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
77 static int arm_dump_node(ir_node *n, FILE *F, 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));
131 /* Returns the attributes of a generic Arm node. */
132 arm_attr_t *get_arm_attr(ir_node *node)
134 assert(is_arm_irn(node) && "need arm node to get attributes");
135 return get_irn_generic_attr(node);
138 const arm_attr_t *get_arm_attr_const(const ir_node *node)
140 assert(is_arm_irn(node) && "need arm node to get attributes");
141 return get_irn_generic_attr_const(node);
145 * Returns the attributes of an ARM SymConst node.
147 arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node)
149 assert(is_arm_SymConst(node) || is_arm_FrameAddr(node));
150 return get_irn_generic_attr(node);
153 const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node)
155 assert(is_arm_SymConst(node) || is_arm_FrameAddr(node));
156 return get_irn_generic_attr_const(node);
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);
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);
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) {
188 assert(is_arm_SwitchJmp(node));
189 return get_irn_generic_attr(node);
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);
198 * Returns the argument register requirements of a arm node.
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);
206 * Returns the argument register requirement at position pos of an arm node.
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];
214 * Sets the IN register requirements at position pos.
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;
222 * Returns the fpaConst value
224 tarval *get_fpaConst_value(const ir_node *node) {
225 const arm_fpaConst_attr_t *attr = get_arm_fpaConst_attr_const(node);
230 * Sets the tarval value
232 void set_fpaConst_value(ir_node *node, tarval *tv) {
233 arm_fpaConst_attr_t *attr = get_arm_fpaConst_attr(node);
238 * Returns the proj num
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;
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;
254 * Returns the number of projs of a SwitchJmp.
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;
262 * Sets the number of projs.
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;
270 * Returns the default_proj_num.
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;
278 * Sets the default_proj_num.
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;
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,
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;
297 arch_irn_set_flags(node, flags);
298 attr->in_req = in_reqs;
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]));
306 static void init_arm_load_store_attributes(ir_node *res, ir_mode *ls_mode,
308 int entity_sign, long offset,
309 bool is_frame_entity)
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;
320 static void init_arm_shifter_operand(ir_node *res, unsigned immediate_value,
321 arm_shift_modifier shift_modifier,
322 unsigned shift_immediate)
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;
330 static void init_arm_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
332 arm_cmp_attr_t *attr = get_irn_generic_attr(res);
333 attr->ins_permuted = ins_permuted;
334 attr->is_unsigned = is_unsigned;
337 static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity)
339 arm_SymConst_attr_t *attr = get_irn_generic_attr(res);
340 attr->entity = entity;
344 static void init_arm_CopyB_attributes(ir_node *res, unsigned size)
346 arm_CopyB_attr_t *attr = get_irn_generic_attr(res);
350 static int cmp_attr_arm(ir_node *a, ir_node *b)
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;
357 static int cmp_attr_arm_SymConst(ir_node *a, ir_node *b)
359 const arm_SymConst_attr_t *attr_a;
360 const arm_SymConst_attr_t *attr_b;
362 if (cmp_attr_arm(a, b))
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;
371 static int cmp_attr_arm_CopyB(ir_node *a, ir_node *b)
373 const arm_CopyB_attr_t *attr_a;
374 const arm_CopyB_attr_t *attr_b;
376 if (cmp_attr_arm(a, b))
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;
384 static int cmp_attr_arm_CondJmp(ir_node *a, ir_node *b)
388 /* never identical */
392 static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b)
396 /* never identical */
400 static int cmp_attr_arm_fpaConst(ir_node *a, ir_node *b)
402 const arm_fpaConst_attr_t *attr_a;
403 const arm_fpaConst_attr_t *attr_b;
405 if (cmp_attr_arm(a, b))
408 attr_a = get_arm_fpaConst_attr_const(a);
409 attr_b = get_arm_fpaConst_attr_const(b);
411 return attr_a->tv != attr_b->tv;
415 arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node)
417 return (arm_load_store_attr_t*) get_irn_generic_attr(node);
420 const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node)
422 return (const arm_load_store_attr_t*) get_irn_generic_attr_const(node);
425 arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node)
427 return (arm_shifter_operand_t*) get_irn_generic_attr(node);
430 static int cmp_attr_arm_load_store(ir_node *a, ir_node *b)
432 const arm_load_store_attr_t *attr_a;
433 const arm_load_store_attr_t *attr_b;
435 if (cmp_attr_arm(a, b))
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)
448 static int cmp_attr_arm_shifter_operand(ir_node *a, ir_node *b)
450 const arm_shifter_operand_t *attr_a;
451 const arm_shifter_operand_t *attr_b;
453 if (cmp_attr_arm(a, b))
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)
466 static int cmp_attr_arm_cmp(ir_node *a, ir_node *b)
468 const arm_cmp_attr_t *attr_a;
469 const arm_cmp_attr_t *attr_b;
471 if (cmp_attr_arm(a, b))
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)
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);
491 /* copy the attributes */
492 memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
495 new_info->out_infos =
496 DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
501 /* Include the generated constructor functions */
502 #include "gen_arm_new_nodes.c.inl"