2 * This file implements the creation of the architecture specific firm opcodes
3 * and the corresponding node constructors for the arm assembler irg.
13 #include "irgraph_t.h"
19 #include "firm_common_t.h"
24 #include "../bearch_t.h"
26 #include "arm_nodes_attr.h"
27 #include "arm_new_nodes.h"
28 #include "gen_arm_regalloc_if_t.h"
31 #include "bearch_arm_t.h"
34 * Returns the shift modifier string.
36 const char *arm_shf_mod_name(arm_shift_modifier mod) {
37 static const char *names[] = { NULL, NULL, "asr", "lsl", "lsr", "ror", "rrx" };
41 /***********************************************************************************
44 * __| |_ _ _ __ ___ _ __ ___ _ __ _ _ __ | |_ ___ _ __| |_ __ _ ___ ___
45 * / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__| _/ _` |/ __/ _ \
46 * | (_| | |_| | | | | | | |_) | __/ | | | | | | || __/ | | || (_| | (_| __/
47 * \__,_|\__,_|_| |_| |_| .__/ \___|_| |_|_| |_|\__\___|_| |_| \__,_|\___\___|
50 ***********************************************************************************/
53 * Dumps the register requirements for either in or out.
55 static void dump_reg_req(FILE *F, const ir_node *node,
56 const arch_register_req_t **reqs, int inout) {
57 char *dir = inout ? "out" : "in";
58 int max = inout ? get_arm_n_res(node) : get_irn_arity(node);
62 memset(buf, 0, sizeof(buf));
65 for (i = 0; i < max; i++) {
66 fprintf(F, "%sreq #%d =", dir, i);
68 if (reqs[i]->type == arch_register_req_type_none) {
72 if (reqs[i]->type & arch_register_req_type_normal) {
73 fprintf(F, " %s", reqs[i]->cls->name);
76 if (reqs[i]->type & arch_register_req_type_limited) {
78 arch_register_req_format(buf, sizeof(buf), reqs[i], node));
81 if (reqs[i]->type & arch_register_req_type_should_be_same) {
82 ir_fprintf(F, " same as %+F", get_irn_n(node, reqs[i]->other_same));
85 if (reqs[i]->type & arch_register_req_type_should_be_different) {
86 ir_fprintf(F, " different from %+F", get_irn_n(node, reqs[i]->other_different));
94 fprintf(F, "%sreq = N/A\n", dir);
99 * Dumper interface for dumping arm nodes in vcg.
100 * @param n the node to dump
101 * @param F the output file
102 * @param reason indicates which kind of information should be dumped
103 * @return 0 on success or != 0 on failure
105 static int arm_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
106 ir_mode *mode = NULL;
109 arm_attr_t *attr = get_arm_attr(n);
110 const arch_register_req_t **reqs;
111 const arch_register_t **slots;
112 arm_shift_modifier mod;
115 case dump_node_opcode_txt:
116 fprintf(F, "%s", get_irn_opname(n));
119 case dump_node_mode_txt:
120 mode = get_irn_mode(n);
123 fprintf(F, "[%s]", get_mode_name(mode));
126 fprintf(F, "[?NOMODE?]");
130 case dump_node_nodeattr_txt:
131 mod = ARM_GET_SHF_MOD(attr);
132 if (ARM_HAS_SHIFT(mod)) {
133 fprintf(F, "[%s #%ld]", arm_shf_mod_name(mod), get_tarval_long(attr->value));
135 else if (mod == ARM_SHF_IMM) {
137 fprintf(F, "[#0x%X]", arm_decode_imm_w_shift(attr->value));
141 case dump_node_info_txt:
142 fprintf(F, "=== arm attr begin ===\n");
144 /* dump IN requirements */
145 if (get_irn_arity(n) > 0) {
146 reqs = get_arm_in_req_all(n);
147 dump_reg_req(F, n, reqs, 0);
150 /* dump OUT requirements */
151 if (attr->n_res > 0) {
152 reqs = get_arm_out_req_all(n);
153 dump_reg_req(F, n, reqs, 1);
156 /* dump assigned registers */
157 slots = get_arm_slots(n);
158 if (slots && attr->n_res > 0) {
159 for (i = 0; i < attr->n_res; i++) {
161 fprintf(F, "reg #%d = %s\n", i, slots[i]->name);
164 fprintf(F, "reg #%d = n/a\n", i);
171 fprintf(F, "n_res = %d\n", get_arm_n_res(n));
174 fprintf(F, "flags =");
175 if (attr->flags == arch_irn_flags_none) {
179 if (attr->flags & arch_irn_flags_dont_spill) {
180 fprintf(F, " unspillable");
182 if (attr->flags & arch_irn_flags_rematerializable) {
183 fprintf(F, " remat");
185 if (attr->flags & arch_irn_flags_ignore) {
186 fprintf(F, " ignore");
189 fprintf(F, " (%d)\n", attr->flags);
191 if (get_arm_value(n)) {
192 if (is_arm_CopyB(n)) {
193 fprintf(F, "size = %lu\n", get_tarval_long(get_arm_value(n)));
195 if (mode_is_float(get_irn_mode(n))) {
196 fprintf(F, "float value = (%f)\n", (double) get_tarval_double(get_arm_value(n)));
197 } else if (mode_is_int(get_irn_mode(n))) {
198 long v = get_tarval_long(get_arm_value(n));
199 fprintf(F, "long value = %ld (0x%08lx)\n", v, v);
200 } else if (mode_is_reference(get_irn_mode(n))) {
201 fprintf(F, "pointer\n");
203 assert(0 && "unbehandelter Typ im const-Knoten");
207 if (get_arm_proj_num(n) >= 0) {
208 fprintf(F, "proj_num = (%d)\n", get_arm_proj_num(n));
210 /* TODO: dump all additional attributes */
212 fprintf(F, "=== arm attr end ===\n");
213 /* end of: case dump_node_info_txt */
221 /***************************************************************************************************
223 * | | | | | | / / | | | | | | | |
224 * __ _| |_| |_ _ __ ___ ___| |_ / /_ _ ___| |_ _ __ ___ ___| |_| |__ ___ __| |___
225 * / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
226 * | (_| | |_| |_| | \__ \ __/ |_ / / (_| | __/ |_ | | | | | | __/ |_| | | | (_) | (_| \__ \
227 * \__,_|\__|\__|_| |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
230 ***************************************************************************************************/
233 * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
234 * Firm was made by people hating const :-(
236 arm_attr_t *get_arm_attr(const ir_node *node) {
237 assert(is_arm_irn(node) && "need arm node to get attributes");
238 return (arm_attr_t *)get_irn_generic_attr((ir_node *)node);
242 * Returns the argument register requirements of a arm node.
244 const arch_register_req_t **get_arm_in_req_all(const ir_node *node) {
245 arm_attr_t *attr = get_arm_attr(node);
250 * Returns the result register requirements of an arm node.
252 const arch_register_req_t **get_arm_out_req_all(const ir_node *node) {
253 arm_attr_t *attr = get_arm_attr(node);
254 return attr->out_req;
258 * Returns the argument register requirement at position pos of an arm node.
260 const arch_register_req_t *get_arm_in_req(const ir_node *node, int pos) {
261 arm_attr_t *attr = get_arm_attr(node);
262 return attr->in_req[pos];
266 * Returns the result register requirement at position pos of an arm node.
268 const arch_register_req_t *get_arm_out_req(const ir_node *node, int pos) {
269 arm_attr_t *attr = get_arm_attr(node);
270 return attr->out_req[pos];
274 * Sets the OUT register requirements at position pos.
276 void set_arm_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
277 arm_attr_t *attr = get_arm_attr(node);
278 attr->out_req[pos] = req;
282 * Sets the complete OUT requirements of node.
284 void set_arm_req_out_all(ir_node *node, const arch_register_req_t **reqs) {
285 arm_attr_t *attr = get_arm_attr(node);
286 attr->out_req = reqs;
290 * Sets the IN register requirements at position pos.
292 void set_arm_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
293 arm_attr_t *attr = get_arm_attr(node);
294 attr->in_req[pos] = req;
298 * Returns the register flag of an arm node.
300 arch_irn_flags_t get_arm_flags(const ir_node *node) {
301 arm_attr_t *attr = get_arm_attr(node);
306 * Sets the register flag of an arm node.
308 void set_arm_flags(const ir_node *node, arch_irn_flags_t flags) {
309 arm_attr_t *attr = get_arm_attr(node);
314 * Returns the result register slots of an arm node.
316 const arch_register_t **get_arm_slots(const ir_node *node) {
317 arm_attr_t *attr = get_arm_attr(node);
322 * Returns the name of the OUT register at position pos.
324 const char *get_arm_out_reg_name(const ir_node *node, int pos) {
325 arm_attr_t *attr = get_arm_attr(node);
327 assert(is_arm_irn(node) && "Not an arm node.");
328 assert(pos < attr->n_res && "Invalid OUT position.");
329 assert(attr->slots[pos] && "No register assigned");
331 return arch_register_get_name(attr->slots[pos]);
335 * Returns the index of the OUT register at position pos within its register class.
337 int get_arm_out_regnr(const ir_node *node, int pos) {
338 arm_attr_t *attr = get_arm_attr(node);
340 assert(is_arm_irn(node) && "Not an arm node.");
341 assert(pos < attr->n_res && "Invalid OUT position.");
342 assert(attr->slots[pos] && "No register assigned");
344 return arch_register_get_index(attr->slots[pos]);
348 * Returns the OUT register at position pos.
350 const arch_register_t *get_arm_out_reg(const ir_node *node, int pos) {
351 arm_attr_t *attr = get_arm_attr(node);
353 assert(is_arm_irn(node) && "Not an arm node.");
354 assert(pos < attr->n_res && "Invalid OUT position.");
355 assert(attr->slots[pos] && "No register assigned");
357 return attr->slots[pos];
361 * Sets the number of results.
363 void set_arm_n_res(ir_node *node, int n_res) {
364 arm_attr_t *attr = get_arm_attr(node);
369 * Returns the number of results.
371 int get_arm_n_res(const ir_node *node) {
372 arm_attr_t *attr = get_arm_attr(node);
376 * Returns the tarvalue
378 tarval *get_arm_value(const ir_node *node) {
379 arm_attr_t *attr = get_arm_attr(node);
386 void set_arm_value(ir_node *node, tarval *tv) {
387 arm_attr_t *attr = get_arm_attr(node);
392 * Returns the proj num
394 int get_arm_proj_num(const ir_node *node) {
395 arm_attr_t *attr = get_arm_attr(node);
396 return attr->proj_num;
402 void set_arm_proj_num(ir_node *node, int proj_num) {
403 arm_attr_t *attr = get_arm_attr(node);
404 attr->proj_num = proj_num;
408 * Returns the SymConst label
410 const char *get_arm_symconst_label(ir_node *node) {
411 arm_attr_t *attr = get_arm_attr(node);
412 return attr->symconst_label;
416 * Sets the SymConst label
418 void set_arm_symconst_label(ir_node *node, const char *symconst_label) {
419 arm_attr_t *attr = get_arm_attr(node);
420 attr->symconst_label = symconst_label;
425 * Returns the number of projs.
427 int get_arm_n_projs(ir_node *node) {
428 arm_attr_t *attr = get_arm_attr(node);
429 return attr->n_projs;
433 * Sets the number of projs.
435 void set_arm_n_projs(ir_node *node, int n_projs) {
436 arm_attr_t *attr = get_arm_attr(node);
437 attr->n_projs = n_projs;
441 * Returns the default_proj_num.
443 long get_arm_default_proj_num(ir_node *node) {
444 arm_attr_t *attr = get_arm_attr(node);
445 return attr->default_proj_num;
449 * Sets the default_proj_num.
451 void set_arm_default_proj_num(ir_node *node, long default_proj_num) {
452 arm_attr_t *attr = get_arm_attr(node);
453 attr->default_proj_num = default_proj_num;
457 * Gets the shift modifier attribute.
459 arm_shift_modifier get_arm_shift_modifier(ir_node *node) {
460 arm_attr_t *attr = get_arm_attr(node);
461 return ARM_GET_SHF_MOD(attr);
464 /* Set the ARM machine node attributes to default values. */
465 void init_arm_attributes(ir_node *node, int flags, const arch_register_req_t ** in_reqs,
466 const arch_register_req_t ** out_reqs, const be_execution_unit_t ***execution_units,
467 int n_res, unsigned latency) {
468 arm_attr_t *attr = get_arm_attr(node);
469 attr->in_req = in_reqs;
470 attr->out_req = out_reqs;
473 attr->instr_fl = (ARM_COND_AL << 3) | ARM_SHF_NONE;
475 attr->proj_num = -42;
476 attr->symconst_label = NULL;
478 attr->default_proj_num = 0;
480 memset((void *)attr->slots, 0, n_res * sizeof(attr->slots[0]));
483 static int arm_comp_condJmp(arm_attr_t *attr_a, arm_attr_t *attr_b) {
488 /***************************************************************************************
491 * _ __ ___ __| | ___ ___ ___ _ __ ___| |_ _ __ _ _ ___| |_ ___ _ __ ___
492 * | '_ \ / _ \ / _` |/ _ \ / __/ _ \| '_ \/ __| __| '__| | | |/ __| __/ _ \| '__/ __|
493 * | | | | (_) | (_| | __/ | (_| (_) | | | \__ \ |_| | | |_| | (__| || (_) | | \__ \
494 * |_| |_|\___/ \__,_|\___| \___\___/|_| |_|___/\__|_| \__,_|\___|\__\___/|_| |___/
496 ***************************************************************************************/
501 #define BIT(x) (1 << (x % 32))
503 static unsigned arm_req_sp_limited[] = { BIT(REG_SP) };
504 static const arch_register_req_t _arm_req_sp = {
505 arch_register_req_type_limited,
506 &arm_reg_classes[CLASS_arm_gp],
512 /* construct Store: Store(ptr, val, mem) = ST ptr,val */
513 ir_node *new_r_arm_StoreStackMInc(ir_graph *irg, ir_node *block, ir_node *mem,
514 ir_node *sp, int n_regs, ir_node **regs,
519 static const arch_register_req_t *_in_req_arm_StoreStackM4Inc[] =
521 &arm_StoreStackM4Inc_reg_req_in_0,
522 &arm_StoreStackM4Inc_reg_req_in_1,
523 &arm_StoreStackM4Inc_reg_req_in_2,
524 &arm_StoreStackM4Inc_reg_req_in_2,
525 &arm_StoreStackM4Inc_reg_req_in_2,
526 &arm_StoreStackM4Inc_reg_req_in_2,
527 &arm_StoreStackM4Inc_reg_req_in_2,
528 &arm_StoreStackM4Inc_reg_req_in_2,
529 &arm_StoreStackM4Inc_reg_req_in_2,
530 &arm_StoreStackM4Inc_reg_req_in_2,
531 &arm_StoreStackM4Inc_reg_req_in_2,
532 &arm_StoreStackM4Inc_reg_req_in_2,
533 &arm_StoreStackM4Inc_reg_req_in_2,
534 &arm_StoreStackM4Inc_reg_req_in_2,
535 &arm_StoreStackM4Inc_reg_req_in_2,
536 &arm_StoreStackM4Inc_reg_req_in_2,
537 &arm_StoreStackM4Inc_reg_req_in_2,
540 assert(n_regs <= 15);
544 memcpy(&in[2], regs, n_regs * sizeof(in[0]));
545 res = new_ir_node(NULL, irg, block, op_arm_StoreStackM4Inc, mode, 2 + n_regs, in);
546 flags |= arch_irn_flags_rematerializable; /* op can be easily recalculated */
548 /* init node attributes */
549 init_arm_attributes(res, flags, _in_req_arm_StoreStackM4Inc, NULL, NULL, 0, 1);
551 res = optimize_node(res);
552 irn_vrfy_irg(res, irg);
557 /************************************************
559 * / _ \ _ __ | |_(_)_ __ ___ (_)_______ _ __ *
560 * | | | | '_ \| __| | '_ ` _ \| |_ / _ \ '__| *
561 * | |_| | |_) | |_| | | | | | | |/ / __/ | *
562 * \___/| .__/ \__|_|_| |_| |_|_/___\___|_| *
564 ************************************************/
566 typedef struct _opt_tuple {
567 ir_op *op_imm_left; /**< immediate is left */
568 ir_op *op_imm_right; /**< immediate is right */
569 ir_op *op_shf_left; /**< shift operand on left */
570 ir_op *op_shf_right; /**< shift operand on right */
573 //static const opt_tuple *opt_ops[iro_arm_last];
575 void arm_set_optimizers(void) {
577 #define STD(op) p_##op = { op_arm_##op##_i, op_arm_##op##_i, op_arm_##op, op_arm_##op }
578 #define LEFT(op) p_##op = { op_arm_##op##_i, NULL, op_arm_##op, NULL }
579 #define SET(op) opt_ops[iro_arm_##op] = &p_##op;
581 static const opt_tuple
590 p_Sub = { op_arm_Sub_i, op_arm_Rsb_i, op_arm_Sub, op_arm_Rsb },
592 memset(opt_ops, 0, sizeof(opt_ops));
606 /* Include the generated constructor functions */
607 #include "gen_arm_new_nodes.c.inl"