+
+ /* phi nodes allow loops, so we use the old arguments for now
+ * and fix this later */
+ phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node), get_irn_in(node) + 1);
+ copy_node_attr(node, phi);
+ be_duplicate_deps(node, phi);
+
+ be_set_transformed_node(node, phi);
+ be_enqueue_preds(node);
+
+ return phi;
+}
+
+/*********************************************************
+ * _ _ _
+ * (_) | | (_)
+ * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
+ * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
+ * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
+ * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
+ *
+ *********************************************************/
+
+/**
+ * the BAD transformer.
+ */
+static ir_node *bad_transform(ir_node *irn) {
+ panic("ARM backend: Not implemented: %+F", irn);
+ return irn;
+}
+
+/**
+ * Set a node emitter. Make it a bit more type safe.
+ */
+static INLINE void set_transformer(ir_op *op, be_transform_func arm_transform_func) {
+ op->ops.generic = (op_func)arm_transform_func;
+}
+
+/**
+ * Enters all transform functions into the generic pointer
+ */
+static void arm_register_transformers(void) {
+ ir_op *op_Max, *op_Min, *op_Mulh;
+
+ /* first clear the generic function pointer for all ops */
+ clear_irp_opcodes_generic_func();
+
+#define GEN(a) set_transformer(op_##a, gen_##a)
+#define BAD(a) set_transformer(op_##a, bad_transform)
+
+ GEN(Add);
+ GEN(Sub);
+ GEN(Mul);
+ GEN(And);
+ GEN(Or);
+ GEN(Eor);
+
+ GEN(Shl);
+ GEN(Shr);
+ GEN(Shrs);
+ GEN(Rotl);
+
+ GEN(Quot);
+
+ /* should be lowered */
+ BAD(Div);
+ BAD(Mod);
+ BAD(DivMod);
+
+ GEN(Minus);
+ GEN(Conv);
+ GEN(Abs);
+ GEN(Not);
+
+ GEN(Load);
+ GEN(Store);
+ GEN(Cond);
+
+ BAD(ASM); /* unsupported yet */
+ GEN(CopyB);
+ BAD(Mux); /* unsupported yet */
+ GEN(Proj);
+ GEN(Phi);
+
+ GEN(Const);
+ GEN(SymConst);
+
+ /* we should never see these nodes */
+ BAD(Raise);
+ BAD(Sel);
+ BAD(InstOf);
+ BAD(Cast);
+ BAD(Free);
+ BAD(Tuple);
+ BAD(Id);
+ //BAD(Bad);
+ BAD(Confirm);
+ BAD(Filter);
+ BAD(CallBegin);
+ BAD(EndReg);
+ BAD(EndExcept);
+
+ /* handle generic backend nodes */
+ GEN(be_FrameAddr);
+ //GEN(be_Call);
+ //GEN(be_Return);
+ GEN(be_AddSP);
+ GEN(be_SubSP);
+ GEN(be_Copy);
+
+ /* set the register for all Unknown nodes */
+ GEN(Unknown);
+
+ op_Max = get_op_Max();
+ if (op_Max)
+ BAD(Max); /* unsupported yet */
+ op_Min = get_op_Min();
+ if (op_Min)
+ BAD(Min); /* unsupported yet */
+ op_Mulh = get_op_Mulh();
+ if (op_Mulh)
+ BAD(Mulh); /* unsupported yet */
+
+#undef GEN
+#undef BAD
+}
+
+/**
+ * Pre-transform all unknown nodes.
+ */
+static void arm_pretransform_node(void *arch_cg) {
+ arm_code_gen_t *cg = arch_cg;
+
+ cg->unknown_gp = be_pre_transform_node(cg->unknown_gp);
+ cg->unknown_fpa = be_pre_transform_node(cg->unknown_fpa);
+}
+
+/**
+ * Initialize fpa Immediate support.
+ */
+static void arm_init_fpa_immediate(void) {
+ /* 0, 1, 2, 3, 4, 5, 10, or 0.5. */
+ fpa_imm[0][fpa_null] = get_tarval_null(mode_F);
+ fpa_imm[0][fpa_one] = get_tarval_one(mode_F);
+ fpa_imm[0][fpa_two] = new_tarval_from_str("2", 1, mode_F);
+ fpa_imm[0][fpa_three] = new_tarval_from_str("3", 1, mode_F);
+ fpa_imm[0][fpa_four] = new_tarval_from_str("4", 1, mode_F);
+ fpa_imm[0][fpa_five] = new_tarval_from_str("5", 1, mode_F);
+ fpa_imm[0][fpa_ten] = new_tarval_from_str("10", 2, mode_F);
+ fpa_imm[0][fpa_half] = new_tarval_from_str("0.5", 3, mode_F);
+
+ fpa_imm[1][fpa_null] = get_tarval_null(mode_D);
+ fpa_imm[1][fpa_one] = get_tarval_one(mode_D);
+ fpa_imm[1][fpa_two] = new_tarval_from_str("2", 1, mode_D);
+ fpa_imm[1][fpa_three] = new_tarval_from_str("3", 1, mode_D);
+ fpa_imm[1][fpa_four] = new_tarval_from_str("4", 1, mode_D);
+ fpa_imm[1][fpa_five] = new_tarval_from_str("5", 1, mode_D);
+ fpa_imm[1][fpa_ten] = new_tarval_from_str("10", 2, mode_D);
+ fpa_imm[1][fpa_half] = new_tarval_from_str("0.5", 3, mode_D);
+
+ fpa_imm[2][fpa_null] = get_tarval_null(mode_E);
+ fpa_imm[2][fpa_one] = get_tarval_one(mode_E);
+ fpa_imm[2][fpa_two] = new_tarval_from_str("2", 1, mode_E);
+ fpa_imm[2][fpa_three] = new_tarval_from_str("3", 1, mode_E);
+ fpa_imm[2][fpa_four] = new_tarval_from_str("4", 1, mode_E);
+ fpa_imm[2][fpa_five] = new_tarval_from_str("5", 1, mode_E);
+ fpa_imm[2][fpa_ten] = new_tarval_from_str("10", 2, mode_E);
+ fpa_imm[2][fpa_half] = new_tarval_from_str("0.5", 3, mode_E);
+}
+
+/**
+ * Transform a Firm graph into an ARM graph.
+ */
+void arm_transform_graph(arm_code_gen_t *cg) {
+ static int imm_initialized = 0;
+
+ if (! imm_initialized) {
+ arm_init_fpa_immediate();
+ imm_initialized = 1;