/**
- * This file implements the creation of the achitecture specific firm opcodes
- * and the coresponding node constructors for the arm assembler irg.
+ * This file implements the creation of the architecture specific firm opcodes
+ * and the corresponding node constructors for the arm assembler irg.
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#ifdef _WIN32
+#ifdef HAVE_MALLOC_H
#include <malloc.h>
-#else
+#endif
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#include "../beabi.h"
#include "bearch_arm_t.h"
+/**
+ * Returns the shift modifier string.
+ */
+const char *arm_shf_mod_name(arm_shift_modifier mod) {
+ static const char *names[] = { NULL, NULL, "asr", "lsl", "lsr", "ror", "rrx" };
+ return names[mod];
+}
/***********************************************************************************
* _ _ _ __
}
}
-
/**
* Dumper interface for dumping arm nodes in vcg.
* @param n the node to dump
* @param reason indicates which kind of information should be dumped
* @return 0 on success or != 0 on failure
*/
-static int dump_node_arm(ir_node *n, FILE *F, dump_reason_t reason) {
- ir_mode *mode = NULL;
+static int arm_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
+ ir_mode *mode = NULL;
int bad = 0;
int i;
- arm_attr_t *attr;
+ arm_attr_t *attr = get_arm_attr(n);
const arm_register_req_t **reqs;
const arch_register_t **slots;
+ arm_shift_modifier mod;
switch (reason) {
case dump_node_opcode_txt:
break;
case dump_node_nodeattr_txt:
-
- /* TODO: dump some attributes which should show up */
- /* in node name in dump (e.g. consts or the like) */
-
+ mod = ARM_GET_SHF_MOD(attr);
+ if (ARM_HAS_SHIFT(mod)) {
+ fprintf(F, "[%s #%ld]", arm_shf_mod_name(mod), get_tarval_long(attr->value));
+ }
+ else if (mod == ARM_SHF_IMM) {
+ /* immediate */
+ fprintf(F, "[#0x%X]", arm_decode_imm_w_shift(attr->value));
+ }
break;
case dump_node_info_txt:
- attr = get_arm_attr(n);
fprintf(F, "=== arm attr begin ===\n");
/* dump IN requirements */
/* end of: case dump_node_info_txt */
break;
}
-
-
return bad;
}
attr->default_proj_num = default_proj_num;
}
+/**
+ * Gets the shift modifier attribute.
+ */
+arm_shift_modifier get_arm_shift_modifier(ir_node *node) {
+ arm_attr_t *attr = get_arm_attr(node);
+ return ARM_GET_SHF_MOD(attr);
+}
-
+/* Set the ARM machine node attributes to default values. */
void init_arm_attributes(ir_node *node, int flags, const arm_register_req_t ** in_reqs,
- const arm_register_req_t ** out_reqs, int n_res) {
+ const arm_register_req_t ** out_reqs, const be_execution_unit_t ***execution_units,
+ int n_res, unsigned latency) {
arm_attr_t *attr = get_arm_attr(node);
- attr->in_req = in_reqs;
- attr->out_req = out_reqs;
- attr->n_res = n_res;
- attr->flags = flags;
- attr->slots = xcalloc(n_res, sizeof(attr->slots[0]));
- attr->value = NULL;
- attr->proj_num = -42;
- attr->symconst_label = NULL;
- attr->n_projs = 0;
+ attr->in_req = in_reqs;
+ attr->out_req = out_reqs;
+ attr->n_res = n_res;
+ attr->flags = flags;
+ attr->instr_fl = (ARM_COND_AL << 3) | ARM_SHF_NONE;
+ attr->value = NULL;
+ attr->proj_num = -42;
+ attr->symconst_label = NULL;
+ attr->n_projs = 0;
attr->default_proj_num = 0;
+
+ memset((void *)attr->slots, 0, n_res * sizeof(attr->slots[0]));
}
static int arm_comp_condJmp(arm_attr_t *attr_a, arm_attr_t *attr_b) {
return 1;
}
-ir_node *arm_new_NoReg_gp(arm_code_gen_t *cg) {
- return be_abi_get_callee_save_irn(cg->birg->abi, &arm_general_purpose_regs[REG_RXX]);
-}
-
-ir_node *arm_new_NoReg_fp(arm_code_gen_t *cg) {
- return be_abi_get_callee_save_irn(cg->birg->abi, &arm_floating_point_regs[REG_FXX]);
-}
-
-
-
/***************************************************************************************
* _ _ _
bitset_clear(bs, 14); /* disallow ignore reg r13 */
bitset_clear(bs, 15); /* disallow ignore reg r15 */
bitset_clear(bs, 16); /* disallow ignore reg rxx */
- bitset_clear(bs, 17); /* disallow ignore reg MURX */
}
static const arm_register_req_t _arm_req_sp = {
{
arch_register_req_type_limited,
- &arm_reg_classes[CLASS_arm_general_purpose],
+ &arm_reg_classes[CLASS_arm_gp],
limit_reg_arm_StoreStackM4Inc_sp,
NULL, /* limit environment */
NULL, /* same node */
{
&arm_default_req_none,
&_arm_req_sp,
- &arm_default_req_arm_general_purpose,
- &arm_default_req_arm_general_purpose,
- &arm_default_req_arm_general_purpose,
- &arm_default_req_arm_general_purpose,
- &arm_default_req_arm_general_purpose,
- &arm_default_req_arm_general_purpose,
- &arm_default_req_arm_general_purpose,
- &arm_default_req_arm_general_purpose,
- &arm_default_req_arm_general_purpose,
- &arm_default_req_arm_general_purpose,
- &arm_default_req_arm_general_purpose,
- &arm_default_req_arm_general_purpose,
- &arm_default_req_arm_general_purpose,
- &arm_default_req_arm_general_purpose,
+ &arm_default_req_arm_gp,
+ &arm_default_req_arm_gp,
+ &arm_default_req_arm_gp,
+ &arm_default_req_arm_gp,
+ &arm_default_req_arm_gp,
+ &arm_default_req_arm_gp,
+ &arm_default_req_arm_gp,
+ &arm_default_req_arm_gp,
+ &arm_default_req_arm_gp,
+ &arm_default_req_arm_gp,
+ &arm_default_req_arm_gp,
+ &arm_default_req_arm_gp,
+ &arm_default_req_arm_gp,
+ &arm_default_req_arm_gp,
};
assert(n_regs <= 15);
flags |= arch_irn_flags_rematerializable; /* op can be easily recalculated */
/* init node attributes */
- init_arm_attributes(res, flags, _in_req_arm_StoreStackM4Inc, NULL, 0);
+ init_arm_attributes(res, flags, _in_req_arm_StoreStackM4Inc, NULL, NULL, 0, 1);
res = optimize_node(res);
irn_vrfy_irg(res, irg);
return res;
}
-/**
- * Register additional opcodes here.
- */
-static void arm_register_additional_opcodes(int cur_opcode) {
+/************************************************
+ * ___ _ _ _ *
+ * / _ \ _ __ | |_(_)_ __ ___ (_)_______ _ __ *
+ * | | | | '_ \| __| | '_ ` _ \| |_ / _ \ '__| *
+ * | |_| | |_) | |_| | | | | | | |/ / __/ | *
+ * \___/| .__/ \__|_|_| |_| |_|_/___\___|_| *
+ * |_| *
+ ************************************************/
+
+typedef struct _opt_tuple {
+ ir_op *op_imm_left; /**< immediate is left */
+ ir_op *op_imm_right; /**< immediate is right */
+ ir_op *op_shf_left; /**< shift operand on left */
+ ir_op *op_shf_right; /**< shift operand on right */
+} opt_tuple;
+
+static const opt_tuple *opt_ops[iro_arm_last];
+
+void arm_set_optimizers(void) {
+ /*
+#define STD(op) p_##op = { op_arm_##op##_i, op_arm_##op##_i, op_arm_##op, op_arm_##op }
+#define LEFT(op) p_##op = { op_arm_##op##_i, NULL, op_arm_##op, NULL }
+#define SET(op) opt_ops[iro_arm_##op] = &p_##op;
+
+ static const opt_tuple
+ STD(Add),
+ STD(And),
+ STD(Or),
+ STD(Eor),
+ LEFT(Bic),
+ LEFT(Shl),
+ LEFT(Shr),
+ LEFT(Shrs),
+ p_Sub = { op_arm_Sub_i, op_arm_Rsb_i, op_arm_Sub, op_arm_Rsb },
+
+ memset(opt_ops, 0, sizeof(opt_ops));
+ SET(Add);
+ SET(And);
+ SET(Or);
+ SET(Eor);
+ SET(Sub);
+ SET(Bic);
+ SET(Shl);
+ SET(Shr);
+ SET(Shrs);
+ */
}