X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Farm%2Farm_transform.c;h=0921fd06b036095f98d1921f8362c1dba228f47a;hb=fcb579b8959da1d7563b1a7b9f008a423ffdf75a;hp=ec1bcfde3a47bc042367d7d8c07a04b275302069;hpb=ad7bf85c4c61ebcd417ce5ce81cbb314bac4b697;p=libfirm diff --git a/ir/be/arm/arm_transform.c b/ir/be/arm/arm_transform.c index ec1bcfde3..0921fd06b 100644 --- a/ir/be/arm/arm_transform.c +++ b/ir/be/arm/arm_transform.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -49,6 +49,7 @@ #include "arm_nodes_attr.h" #include "archop.h" #include "arm_transform.h" +#include "arm_optimize.h" #include "arm_new_nodes.h" #include "arm_map_regs.h" @@ -74,141 +75,70 @@ extern ir_op *get_op_Mulh(void); ****************************************************************************************************/ static INLINE int mode_needs_gp_reg(ir_mode *mode) { - return mode_is_int(mode) || mode_is_character(mode) || mode_is_reference(mode); -} - -typedef struct vals_ { - int ops; - unsigned char values[4]; - unsigned char shifts[4]; -} vals; - -/** Execute ROL. */ -static unsigned do_rol(unsigned v, unsigned rol) { - return (v << rol) | (v >> (32 - rol)); -} - -/** - * construct 8bit values and rot amounts for a value - */ -static void gen_vals_from_word(unsigned int value, vals *result) -{ - int initial = 0; - - memset(result, 0, sizeof(*result)); - - /* special case: we prefer shift amount 0 */ - if (value < 0x100) { - result->values[0] = value; - result->ops = 1; - return; - } - - while (value != 0) { - if (value & 0xFF) { - unsigned v = do_rol(value, 8) & 0xFFFFFF; - int shf = 0; - for (;;) { - if ((v & 3) != 0) - break; - shf += 2; - v >>= 2; - } - v &= 0xFF; - shf = (initial + shf - 8) & 0x1F; - result->values[result->ops] = v; - result->shifts[result->ops] = shf; - ++result->ops; - - value ^= do_rol(v, shf) >> initial; - } - else { - value >>= 8; - initial += 8; - } - } + return mode_is_int(mode) || mode_is_reference(mode); } /** * Creates a arm_Const node. */ -static ir_node *create_const_node(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, long value) { +static ir_node *create_mov_node(dbg_info *dbg, ir_node *block, long value) { ir_mode *mode = mode_Iu; - tarval *tv = new_tarval_from_long(value, mode); + ir_graph *irg = current_ir_graph; ir_node *res; if (mode_needs_gp_reg(mode)) mode = mode_Iu; - res = new_rd_arm_Mov_i(dbg, current_ir_graph, block, mode, tv); - /* ensure the const is schedules AFTER the barrier */ - add_irn_dep(res, be_abi_get_start_barrier(abi)); + res = new_rd_arm_Mov_i(dbg, irg, block, mode, value); + be_dep_on_frame(res); return res; } /** * Creates a arm_Const_Neg node. */ -static ir_node *create_const_neg_node(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, long value) { +static ir_node *create_mvn_node(dbg_info *dbg, ir_node *block, long value) { ir_mode *mode = mode_Iu; - tarval *tv = new_tarval_from_long(value, mode); + ir_graph *irg = current_ir_graph; ir_node *res; if (mode_needs_gp_reg(mode)) mode = mode_Iu; - res = new_rd_arm_Mvn_i(dbg, current_ir_graph, block, mode, tv); - add_irn_dep(res, be_abi_get_start_barrier(abi)); - /* ensure the const is schedules AFTER the barrier */ + res = new_rd_arm_Mvn_i(dbg, irg, block, mode, value); + be_dep_on_frame(res); return res; } #define NEW_BINOP_NODE(opname, env, op1, op2) new_rd_arm_##opname(env->dbg, current_ir_graph, env->block, op1, op2, env->mode) -/** - * Encodes an immediate with shifter operand - */ -static unsigned int arm_encode_imm_w_shift(unsigned int shift, unsigned int immediate) { - return immediate | ((shift>>1)<<8); -} - -/** - * Decode an immediate with shifter operand - */ -unsigned int arm_decode_imm_w_shift(tarval *tv) { - unsigned l = get_tarval_long(tv); - unsigned rol = (l & ~0xFF) >> 7; - - return do_rol(l & 0xFF, rol); -} - /** * Creates a possible DAG for an constant. */ -static ir_node *create_const_graph_value(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, unsigned int value) { +static ir_node *create_const_graph_value(dbg_info *dbg, ir_node *block, unsigned int value) { ir_node *result; - vals v, vn; + arm_vals v, vn; int cnt; ir_mode *mode = mode_Iu; - gen_vals_from_word(value, &v); - gen_vals_from_word(~value, &vn); + arm_gen_vals_from_word(value, &v); + arm_gen_vals_from_word(~value, &vn); if (vn.ops < v.ops) { /* remove bits */ - result = create_const_neg_node(abi, dbg, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0])); + result = create_mvn_node(dbg, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0])); for (cnt = 1; cnt < vn.ops; ++cnt) { - tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]), mode); - ir_node *bic_i_node = new_rd_arm_Bic_i(dbg, current_ir_graph, block, result, mode, tv); + long value = arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]); + ir_node *bic_i_node = new_rd_arm_Bic_i(dbg, current_ir_graph, block, result, mode, value); result = bic_i_node; } } else { /* add bits */ - result = create_const_node(abi, dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0])); + result = create_mov_node(dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0])); for (cnt = 1; cnt < v.ops; ++cnt) { - tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]), mode); - ir_node *orr_i_node = new_rd_arm_Or_i(dbg, current_ir_graph, block, result, mode, tv); + long value = arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]); + ir_node *orr_i_node = new_rd_arm_Or_i(dbg, current_ir_graph, block, result, mode, value); result = orr_i_node; } } @@ -220,7 +150,7 @@ static ir_node *create_const_graph_value(be_abi_irg_t *abi, dbg_info *dbg, ir_no * * @param irn a Firm const */ -static ir_node *create_const_graph(be_abi_irg_t *abi, ir_node *irn, ir_node *block) { +static ir_node *create_const_graph(ir_node *irn, ir_node *block) { tarval *tv = get_Const_tarval(irn); ir_mode *mode = get_tarval_mode(tv); int value; @@ -231,25 +161,25 @@ static ir_node *create_const_graph(be_abi_irg_t *abi, ir_node *irn, ir_node *blo tv = tarval_convert_to(tv, mode_Iu); } value = get_tarval_long(tv); - return create_const_graph_value(abi, get_irn_dbg_info(irn), block, value); + return create_const_graph_value(get_irn_dbg_info(irn), block, value); } /** * Create an And that will mask all upper bits */ -static ir_node *gen_zero_extension(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) { +static ir_node *gen_zero_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) { unsigned mask_bits = (1 << result_bits) - 1; - ir_node *mask_node = create_const_graph_value(abi, dbg, block, mask_bits); - return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, mode_Iu, ARM_SHF_NONE, NULL); + ir_node *mask_node = create_const_graph_value(dbg, block, mask_bits); + return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, mode_Iu, ARM_SHF_NONE, 0); } /** * Generate code for a sign extension. */ -static ir_node *gen_sign_extension(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) { +static ir_node *gen_sign_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) { ir_graph *irg = current_ir_graph; int shift_width = 32 - result_bits; - ir_node *shift_const_node = create_const_graph_value(abi, dbg, block, shift_width); + ir_node *shift_const_node = create_const_graph_value(dbg, block, shift_width); ir_node *lshift_node = new_rd_arm_Shl(dbg, irg, block, op, shift_const_node, mode_Iu); ir_node *rshift_node = new_rd_arm_Shrs(dbg, irg, block, lshift_node, shift_const_node, mode_Iu); return rshift_node; @@ -279,7 +209,7 @@ static ir_node *gen_Conv(ir_node *node) { if (mode_is_float(src_mode)) { if (mode_is_float(dst_mode)) { /* from float to float */ - return new_rd_arm_fpaMov(dbg, irg, block, new_op, dst_mode); + return new_rd_arm_fpaMvf(dbg, irg, block, new_op, dst_mode); } else { /* from float to int */ @@ -292,11 +222,11 @@ static ir_node *gen_Conv(ir_node *node) { } } else if (USE_VFP(env_cg->isa)) { - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); return NULL; } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); return NULL; } } @@ -327,12 +257,12 @@ static ir_node *gen_Conv(ir_node *node) { min_mode = dst_mode; } if (mode_is_signed(min_mode)) { - return gen_sign_extension(env_cg->birg->abi, dbg, block, new_op, min_bits); + return gen_sign_extension(dbg, block, new_op, min_bits); } else { - return gen_zero_extension(env_cg->birg->abi, dbg, block, new_op, min_bits); + return gen_zero_extension(dbg, block, new_op, min_bits); } } else { - panic("Cannot handle Conv %+F->%+F with %d->%d bits\n", src_mode, dst_mode, + panic("Cannot handle Conv %+F->%+F with %d->%d bits", src_mode, dst_mode, src_bits, dst_bits); return NULL; } @@ -350,7 +280,7 @@ static int is_shifter_operand(ir_node *n, arm_shift_modifier *pmod) { *pmod = mod; if (mod != ARM_SHF_NONE) { - long v = get_tarval_long(get_arm_value(n)); + long v = get_arm_imm_value(n); if (v < 32) return (int)v; } @@ -377,35 +307,39 @@ static ir_node *gen_Add(ir_node *node) { if (mode_is_float(mode)) { env_cg->have_fp_insn = 1; - if (USE_FPA(env_cg->isa)) - return new_rd_arm_fpaAdd(dbg, irg, block, new_op1, new_op2, mode); - else if (USE_VFP(env_cg->isa)) { + if (USE_FPA(env_cg->isa)) { + if (is_arm_fpaMvf_i(new_op1)) + return new_rd_arm_fpaAdf_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1)); + if (is_arm_fpaMvf_i(new_op2)) + return new_rd_arm_fpaAdf_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2)); + return new_rd_arm_fpaAdf(dbg, irg, block, new_op1, new_op2, mode); + } else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); return NULL; } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); return NULL; } } else { - assert(mode_is_numP(mode)); + assert(mode_is_data(mode)); mode = mode_Iu; if (is_arm_Mov_i(new_op1)) - return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1)); + return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1)); if (is_arm_Mov_i(new_op2)) - return new_rd_arm_Add_i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2)); + return new_rd_arm_Add_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2)); /* check for MLA */ - if (is_arm_Mul(new_op1) && get_irn_n_edges(new_op1) == 1) { + if (is_arm_Mul(new_op1) && get_irn_n_edges(op1) == 1) { new_op3 = new_op2; - op2 = get_irn_n(new_op1, 1); - op1 = get_irn_n(new_op1, 0); + new_op2 = get_irn_n(new_op1, 1); + new_op1 = get_irn_n(new_op1, 0); return new_rd_arm_Mla(dbg, irg, block, new_op1, new_op2, new_op3, mode); } - if (is_arm_Mul(new_op2) && get_irn_n_edges(new_op2) == 1) { + if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) { new_op3 = new_op1; new_op1 = get_irn_n(new_op2, 0); new_op2 = get_irn_n(new_op2, 1); @@ -417,17 +351,17 @@ static ir_node *gen_Add(ir_node *node) { v = is_shifter_operand(new_op1, &mod); if (v) { new_op1 = get_irn_n(new_op1, 0); - return new_rd_arm_Add(dbg, irg, block, new_op2, new_op1, mode, mod, new_tarval_from_long(v, mode_Iu)); + return new_rd_arm_Add(dbg, irg, block, new_op2, new_op1, mode, mod, v); } /* is the second a shifter */ v = is_shifter_operand(new_op2, &mod); if (v) { new_op2 = get_irn_n(new_op2, 0); - return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, mod, new_tarval_from_long(v, mode_Iu)); + return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, mod, v); } /* normal ADD */ - return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL); + return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0); } } @@ -448,19 +382,24 @@ static ir_node *gen_Mul(ir_node *node) { if (mode_is_float(mode)) { env_cg->have_fp_insn = 1; - if (USE_FPA(env_cg->isa)) - return new_rd_arm_fpaMul(dbg, irg, block, new_op1, new_op2, mode); + if (USE_FPA(env_cg->isa)) { + if (is_arm_Mov_i(new_op1)) + return new_rd_arm_fpaMuf_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1)); + if (is_arm_Mov_i(new_op2)) + return new_rd_arm_fpaMuf_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2)); + return new_rd_arm_fpaMuf(dbg, irg, block, new_op1, new_op2, mode); + } else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); return NULL; } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); return NULL; } } - assert(mode_is_numP(mode)); + assert(mode_is_data(mode)); mode = mode_Iu; return new_rd_arm_Mul(dbg, irg, block, new_op1, new_op2, mode); } @@ -483,14 +422,18 @@ static ir_node *gen_Quot(ir_node *node) { assert(mode != mode_E && "IEEE Extended FP not supported"); env_cg->have_fp_insn = 1; - if (USE_FPA(env_cg->isa)) - return new_rd_arm_fpaDiv(dbg, current_ir_graph, block, new_op1, new_op2, mode); - else if (USE_VFP(env_cg->isa)) { + if (USE_FPA(env_cg->isa)) { + if (is_arm_Mov_i(new_op1)) + return new_rd_arm_fpaRdf_i(dbg, current_ir_graph, block, new_op2, mode, get_arm_imm_value(new_op1)); + if (is_arm_Mov_i(new_op2)) + return new_rd_arm_fpaDvf_i(dbg, current_ir_graph, block, new_op1, mode, get_arm_imm_value(new_op2)); + return new_rd_arm_fpaDvf(dbg, current_ir_graph, block, new_op1, new_op2, mode); + } else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); return NULL; } } @@ -508,23 +451,23 @@ static ir_node *gen_Quot(ir_node *node) { arm_shift_modifier mod; \ \ if (is_arm_Mov_i(new_op1)) \ - return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1)); \ + return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1)); \ if (is_arm_Mov_i(new_op2)) \ - return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2)); \ + return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2)); \ /* is the first a shifter */ \ v = is_shifter_operand(new_op1, &mod); \ if (v) { \ new_op1 = get_irn_n(new_op1, 0); \ - return new_rd_arm_ ## op(dbg, irg, block, new_op2, new_op1, mode, mod, new_tarval_from_long(v, mode_Iu)); \ + return new_rd_arm_ ## op(dbg, irg, block, new_op2, new_op1, mode, mod, v); \ } \ /* is the second a shifter */ \ v = is_shifter_operand(new_op2, &mod); \ if (v) { \ new_op2 = get_irn_n(new_op2, 0); \ - return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, mod, new_tarval_from_long(v, mode_Iu)); \ + return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, mod, v); \ } \ /* Normal op */ \ - return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL) \ + return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0) \ /** * Creates an ARM And. @@ -573,41 +516,45 @@ static ir_node *gen_Sub(ir_node *node) { if (mode_is_float(mode)) { env_cg->have_fp_insn = 1; - if (USE_FPA(env_cg->isa)) - return new_rd_arm_fpaSub(dbg, irg, block, new_op1, new_op2, mode); - else if (USE_VFP(env_cg->isa)) { + if (USE_FPA(env_cg->isa)) { + if (is_arm_Mov_i(new_op1)) + return new_rd_arm_fpaRsf_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1)); + if (is_arm_Mov_i(new_op2)) + return new_rd_arm_fpaSuf_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2)); + return new_rd_arm_fpaSuf(dbg, irg, block, new_op1, new_op2, mode); + } else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); return NULL; } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); return NULL; } } else { - assert(mode_is_numP(mode) && "unknown mode for Sub"); + assert(mode_is_data(mode) && "unknown mode for Sub"); mode = mode_Iu; if (is_arm_Mov_i(new_op1)) - return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1)); + return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1)); if (is_arm_Mov_i(new_op2)) - return new_rd_arm_Sub_i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2)); + return new_rd_arm_Sub_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2)); /* is the first a shifter */ v = is_shifter_operand(new_op1, &mod); if (v) { new_op1 = get_irn_n(new_op1, 0); - return new_rd_arm_Rsb(dbg, irg, block, new_op2, new_op1, mode, mod, new_tarval_from_long(v, mode_Iu)); + return new_rd_arm_Rsb(dbg, irg, block, new_op2, new_op1, mode, mod, v); } /* is the second a shifter */ v = is_shifter_operand(new_op2, &mod); if (v) { new_op2 = get_irn_n(new_op2, 0); - return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, mod, new_tarval_from_long(v, mode_Iu)); + return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, mod, v); } /* normal sub */ - return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL); + return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0); } } @@ -626,7 +573,7 @@ static ir_node *gen_Shl(ir_node *node) { dbg_info *dbg = get_irn_dbg_info(node); if (is_arm_Mov_i(new_op2)) { - return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSL, get_arm_value(new_op2)); + return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSL, get_arm_imm_value(new_op2)); } return new_rd_arm_Shl(dbg, current_ir_graph, block, new_op1, new_op2, mode); } @@ -646,7 +593,7 @@ static ir_node *gen_Shr(ir_node *node) { dbg_info *dbg = get_irn_dbg_info(node); if (is_arm_Mov_i(new_op2)) { - return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSR, get_arm_value(new_op2)); + return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSR, get_arm_imm_value(new_op2)); } return new_rd_arm_Shr(dbg, current_ir_graph, block, new_op1, new_op2, mode); } @@ -666,11 +613,111 @@ static ir_node *gen_Shrs(ir_node *node) { dbg_info *dbg = get_irn_dbg_info(node); if (is_arm_Mov_i(new_op2)) { - return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ASR, get_arm_value(new_op2)); + return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ASR, get_arm_imm_value(new_op2)); } return new_rd_arm_Shrs(dbg, current_ir_graph, block, new_op1, new_op2, mode); } +/** + * Creates an ARM Ror. + * + * @return the created ARM Ror node + */ +static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *new_op1 = be_transform_node(op1); + ir_node *new_op2 = be_transform_node(op2); + ir_mode *mode = mode_Iu; + dbg_info *dbg = get_irn_dbg_info(node); + + if (is_arm_Mov_i(new_op2)) { + return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ROR, get_arm_imm_value(new_op2)); + } + return new_rd_arm_Ror(dbg, current_ir_graph, block, new_op1, new_op2, mode); +} + +/** + * Creates an ARM Rol. + * + * @return the created ARM Rol node + * + * Note: there is no Rol on arm, we have to use Ror + */ +static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *new_op1 = be_transform_node(op1); + ir_mode *mode = mode_Iu; + dbg_info *dbg = get_irn_dbg_info(node); + ir_node *new_op2 = be_transform_node(op2); + + new_op2 = new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op2, mode, 32); + return new_rd_arm_Ror(dbg, current_ir_graph, block, new_op1, new_op2, mode); +} + +/** + * Creates an ARM ROR from a Firm Rotl. + * + * @return the created ARM Ror node + */ +static ir_node *gen_Rotl(ir_node *node) { + ir_node *rotate = NULL; + ir_node *op1 = get_Rotl_left(node); + ir_node *op2 = get_Rotl_right(node); + + /* Firm has only RotL, so we are looking for a right (op2) + operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e", + that means we can create a RotR. */ + + if (is_Add(op2)) { + ir_node *right = get_Add_right(op2); + if (is_Const(right)) { + tarval *tv = get_Const_tarval(right); + ir_mode *mode = get_irn_mode(node); + long bits = get_mode_size_bits(mode); + ir_node *left = get_Add_left(op2); + + if (is_Minus(left) && + tarval_is_long(tv) && + get_tarval_long(tv) == bits && + bits == 32) + rotate = gen_Ror(node, op1, get_Minus_op(left)); + } + } else if (is_Sub(op2)) { + ir_node *left = get_Sub_left(op2); + if (is_Const(left)) { + tarval *tv = get_Const_tarval(left); + ir_mode *mode = get_irn_mode(node); + long bits = get_mode_size_bits(mode); + ir_node *right = get_Sub_right(op2); + + if (tarval_is_long(tv) && + get_tarval_long(tv) == bits && + bits == 32) + rotate = gen_Ror(node, op1, right); + } + } else if (is_Const(op2)) { + tarval *tv = get_Const_tarval(op2); + ir_mode *mode = get_irn_mode(node); + long bits = get_mode_size_bits(mode); + + if (tarval_is_long(tv) && bits == 32) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *new_op1 = be_transform_node(op1); + ir_mode *mode = mode_Iu; + dbg_info *dbg = get_irn_dbg_info(node); + + bits = (bits - get_tarval_long(tv)) & 31; + rotate = new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ROR, bits); + } + } + + if (rotate == NULL) { + rotate = gen_Rol(node, op1, op2); + } + + return rotate; +} + /** * Transforms a Not node. * @@ -681,16 +728,14 @@ static ir_node *gen_Not(ir_node *node) { ir_node *op = get_Not_op(node); ir_node *new_op = be_transform_node(op); dbg_info *dbg = get_irn_dbg_info(node); - tarval *tv = NULL; ir_mode *mode = mode_Iu; arm_shift_modifier mod = ARM_SHF_NONE; int v = is_shifter_operand(new_op, &mod); if (v) { new_op = get_irn_n(new_op, 0); - tv = new_tarval_from_long(v, mode_Iu); } - return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, mode, mod, tv); + return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, mode, mod, v); } /** @@ -712,13 +757,13 @@ static ir_node *gen_Abs(ir_node *node) { return new_rd_arm_fpaAbs(dbg, current_ir_graph, block, new_op, mode); else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); } } - assert(mode_is_numP(mode)); + assert(mode_is_data(mode)); mode = mode_Iu; return new_rd_arm_Abs(dbg, current_ir_graph, block, new_op, mode); } @@ -738,18 +783,18 @@ static ir_node *gen_Minus(ir_node *node) { if (mode_is_float(mode)) { env_cg->have_fp_insn = 1; if (USE_FPA(env_cg->isa)) - return new_rd_arm_fpaMnv(dbg, current_ir_graph, block, op, mode); + return new_rd_arm_fpaMvf(dbg, current_ir_graph, block, op, mode); else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); } } - assert(mode_is_numP(mode)); + assert(mode_is_data(mode)); mode = mode_Iu; - return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, get_mode_null(mode)); + return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, 0); } /** @@ -774,14 +819,14 @@ static ir_node *gen_Load(ir_node *node) { new_load = new_rd_arm_fpaLdf(dbg, irg, block, new_ptr, new_mem, mode); else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); } } else { - assert(mode_is_numP(mode) && "unsupported mode for Load"); + assert(mode_is_data(mode) && "unsupported mode for Load"); if (mode_is_signed(mode)) { /* sign extended loads */ @@ -796,7 +841,7 @@ static ir_node *gen_Load(ir_node *node) { new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem); break; default: - panic("mode size not supported\n"); + panic("mode size not supported"); } } else { /* zero extended loads */ @@ -811,7 +856,7 @@ static ir_node *gen_Load(ir_node *node) { new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem); break; default: - panic("mode size not supported\n"); + panic("mode size not supported"); } } } @@ -821,7 +866,7 @@ static ir_node *gen_Load(ir_node *node) { if (be_get_Proj_for_pn(node, pn_Load_res) == NULL) { /* add a result proj and a Keep to produce a pseudo use */ ir_node *proj = new_r_Proj(irg, block, new_load, mode_Iu, pn_arm_Load_res); - be_new_Keep(arch_get_irn_reg_class(env_cg->arch_env, proj, -1), irg, block, 1, &proj); + be_new_Keep(arch_get_irn_reg_class(proj, -1), irg, block, 1, &proj); } return new_load; @@ -851,12 +896,12 @@ static ir_node *gen_Store(ir_node *node) { new_store = new_rd_arm_fpaStf(dbg, irg, block, new_ptr, new_val, new_mem, mode); else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); } } else { - assert(mode_is_numP(mode) && "unsupported mode for Store"); + assert(mode_is_data(mode) && "unsupported mode for Store"); switch (get_mode_size_bits(mode)) { case 8: new_store = new_rd_arm_Storeb(dbg, irg, block, new_ptr, new_val, new_mem); @@ -883,14 +928,31 @@ static ir_node *gen_Cond(ir_node *node) { ir_mode *mode = get_irn_mode(selector); if (mode == mode_b) { - /* CondJmp */ + /* an conditional jump */ ir_node *cmp_node = get_Proj_pred(selector); ir_node *op1 = get_Cmp_left(cmp_node); ir_node *new_op1 = be_transform_node(op1); ir_node *op2 = get_Cmp_right(cmp_node); - ir_node *new_op2 = be_transform_node(op2); - return new_rd_arm_CondJmp(dbg, irg, block, new_op1, new_op2, get_Proj_proj(selector)); + if (mode_is_float(get_irn_mode(op1))) { + ir_node *new_op2 = be_transform_node(op2); + /* floating point compare */ + pn_Cmp pnc = get_Proj_proj(selector); + + if (pnc & pn_Cmp_Uo) { + /* check for unordered, need cmf */ + return new_rd_arm_fpaCmfBra(dbg, irg, block, new_op1, new_op2, pnc); + } + /* Hmm: use need cmfe */ + return new_rd_arm_fpaCmfeBra(dbg, irg, block, new_op1, new_op2, pnc); + } else if (is_Const(op2) && tarval_is_null(get_Const_tarval(op2))) { + /* compare with 0 */ + return new_rd_arm_TstBra(dbg, irg, block, new_op1, new_op1, get_Proj_proj(selector)); + } else { + /* integer compare */ + ir_node *new_op2 = be_transform_node(op2); + return new_rd_arm_CmpBra(dbg, irg, block, new_op1, new_op2, get_Proj_proj(selector)); + } } else { /* SwitchJmp */ ir_node *new_op = be_transform_node(selector); @@ -925,9 +987,8 @@ static ir_node *gen_Cond(ir_node *node) { set_Proj_proj(proj, pn); } - - const_graph = create_const_graph_value(env_cg->birg->abi, dbg, block, translation); - sub = new_rd_arm_Sub(dbg, irg, block, new_op, const_graph, mode, ARM_SHF_NONE, NULL); + const_graph = create_const_graph_value(dbg, block, translation); + sub = new_rd_arm_Sub(dbg, irg, block, new_op, const_graph, mode, ARM_SHF_NONE, 0); return new_rd_arm_SwitchJmp(dbg, irg, block, sub, n_projs, get_Cond_defaultProj(node) - translation); } } @@ -946,7 +1007,7 @@ static ident *get_sc_ident(ir_node *symc) { case symconst_addr_ent: ent = get_SymConst_entity(symc); - mark_entity_visited(ent); + set_entity_backend_marked(ent, 1); return get_entity_ld_ident(ent); default: @@ -956,6 +1017,39 @@ static ident *get_sc_ident(ir_node *symc) { return NULL; } +static tarval *fpa_imm[3][fpa_max]; + +/** + * Check, if a floating point tarval is an fpa immediate, i.e. + * one of 0, 1, 2, 3, 4, 5, 10, or 0.5. + */ +static int is_fpa_immediate(tarval *tv) { + ir_mode *mode = get_tarval_mode(tv); + int i, j, res = 1; + + switch (get_mode_size_bits(mode)) { + case 32: + i = 0; + break; + case 64: + i = 1; + break; + default: + i = 2; + } + + if (tarval_cmp(tv, get_tarval_null(mode)) & pn_Cmp_Lt) { + tv = tarval_neg(tv); + res = -1; + } + + for (j = 0; j < fpa_max; ++j) { + if (tv == fpa_imm[i][j]) + return res * j; + } + return fpa_max; +} + /** * Transforms a Const node. * @@ -970,20 +1064,29 @@ static ir_node *gen_Const(ir_node *node) { if (mode_is_float(mode)) { env_cg->have_fp_insn = 1; if (USE_FPA(env_cg->isa)) { - node = new_rd_arm_fpaConst(dbg, irg, block, get_Const_tarval(node)); - /* ensure the const is schedules AFTER the barrier */ - add_irn_dep(node, be_abi_get_start_barrier(env_cg->birg->abi)); + tarval *tv = get_Const_tarval(node); + int imm = is_fpa_immediate(tv); + + if (imm != fpa_max) { + if (imm > 0) + node = new_rd_arm_fpaMvf_i(dbg, irg, block, mode, imm); + else + node = new_rd_arm_fpaMnf_i(dbg, irg, block, mode, -imm); + } else { + node = new_rd_arm_fpaConst(dbg, irg, block, tv); + } + be_dep_on_frame(node); return node; } else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); } } - return create_const_graph(env_cg->birg->abi, node, block); + return create_const_graph(node, block); } /** @@ -995,11 +1098,11 @@ static ir_node *gen_SymConst(ir_node *node) { ir_node *block = be_transform_node(get_nodes_block(node)); ir_mode *mode = mode_Iu; dbg_info *dbg = get_irn_dbg_info(node); + ir_graph *irg = current_ir_graph; ir_node *res; - res = new_rd_arm_SymConst(dbg, current_ir_graph, block, mode, get_sc_ident(node)); - add_irn_dep(res, be_abi_get_start_barrier(env_cg->birg->abi)); - /* ensure the const is schedules AFTER the barrier */ + res = new_rd_arm_SymConst(dbg, irg, block, mode, get_sc_ident(node)); + be_dep_on_frame(res); return res; } @@ -1029,7 +1132,7 @@ static ir_node *gen_CopyB(ir_node *node) { new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), - new_mem, new_tarval_from_long(size, mode_Iu)); + new_mem, size); } @@ -1120,50 +1223,12 @@ static ir_node *gen_be_FrameAddr(ir_node *node) { is relative. Both must be merged */ offset += get_sp_expand_offset(op); } - cnst = create_const_graph_value(env_cg->birg->abi, dbg, block, (unsigned)offset); + cnst = create_const_graph_value(dbg, block, (unsigned)offset); if (is_arm_Mov_i(cnst)) - return new_rd_arm_Add_i(dbg, current_ir_graph, block, new_op, mode, get_arm_value(cnst)); - return new_rd_arm_Add(dbg, current_ir_graph, block, new_op, cnst, mode, ARM_SHF_NONE, NULL); + return new_rd_arm_Add_i(dbg, current_ir_graph, block, new_op, mode, get_arm_imm_value(cnst)); + return new_rd_arm_Add(dbg, current_ir_graph, block, new_op, cnst, mode, ARM_SHF_NONE, 0); } -#if 0 -/** - * Transforms a FrameLoad into an ARM Load. - */ -static ir_node *gen_FrameLoad(ir_node *irn) { - ir_node *new_op = NULL; - ir_node *noreg = ia32_new_NoReg_gp(env->cg); - ir_node *mem = get_irn_n(irn, 0); - ir_node *ptr = get_irn_n(irn, 1); - ir_entity *ent = be_get_frame_entity(irn); - ir_mode *mode = get_type_mode(get_entity_type(ent)); - - if (mode_is_float(mode)) { - if (USE_SSE2(env->cg)) - new_op = new_rd_ia32_fLoad(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T); - else { - env->cg->used_x87 = 1; - new_op = new_rd_ia32_vfld(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T); - } - } - else { - new_op = new_rd_ia32_Load(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T); - } - - set_ia32_frame_ent(new_op, ent); - set_ia32_use_frame(new_op); - - set_ia32_am_support(new_op, ia32_am_Source); - set_ia32_op_type(new_op, ia32_AddrModeS); - set_ia32_am_flavour(new_op, ia32_B); - set_ia32_ls_mode(new_op, mode); - - SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn)); - - return new_op; -} -#endif - /** * Transform a be_AddSP into an arm_AddSP. Eat up const sizes. */ @@ -1178,8 +1243,8 @@ static ir_node *gen_be_AddSP(ir_node *node) { ir_node *nomem = new_NoMem(); ir_node *new_op; - /* ARM stack grows in reverse direction, make a SubSP */ - new_op = new_rd_arm_SubSP(dbgi, irg, block, new_sp, new_sz, nomem); + /* ARM stack grows in reverse direction, make a SubSPandCopy */ + new_op = new_rd_arm_SubSPandCopy(dbgi, irg, block, new_sp, new_sz, nomem); return new_op; } @@ -1254,8 +1319,7 @@ static ir_node *gen_Proj_Load(ir_node *node) { default: break; } - assert(0); - return new_rd_Unknown(irg, get_irn_mode(node)); + panic("Unsupported Proj from Load"); } /** @@ -1267,7 +1331,6 @@ static ir_node *gen_Proj_CopyB(ir_node *node) { ir_node *new_pred = be_transform_node(pred); ir_graph *irg = current_ir_graph; dbg_info *dbgi = get_irn_dbg_info(node); - ir_mode *mode = get_irn_mode(node); long proj = get_Proj_proj(node); switch(proj) { @@ -1279,8 +1342,7 @@ static ir_node *gen_Proj_CopyB(ir_node *node) { default: break; } - assert(0); - return new_rd_Unknown(irg, mode); + panic("Unsupported Proj from CopyB"); } /** @@ -1297,36 +1359,35 @@ static ir_node *gen_Proj_Quot(ir_node *node) { switch (proj) { case pn_Quot_M: - if (is_arm_fpaDiv(new_pred)) { - return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaDiv_M); - } else if (is_arm_fpaRdv(new_pred)) { - return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaRdv_M); - } else if (is_arm_fpaFDiv(new_pred)) { - return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFDiv_M); - } else if (is_arm_fpaFRdv(new_pred)) { - return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFRdv_M); + if (is_arm_fpaDvf(new_pred) || is_arm_fpaDvf_i(new_pred)) { + return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaDvf_M); + } else if (is_arm_fpaRdf(new_pred) || is_arm_fpaRdf_i(new_pred)) { + return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaRdf_M); + } else if (is_arm_fpaFdv(new_pred) || is_arm_fpaFdv_i(new_pred)) { + return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFdv_M); + } else if (is_arm_fpaFrd(new_pred) || is_arm_fpaFrd_i(new_pred)) { + return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFrd_M); } break; case pn_Quot_res: - if (is_arm_fpaDiv(new_pred)) { - return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaDiv_res); - } else if (is_arm_fpaFDiv(new_pred)) { - return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaRdv_res); - } else if (is_arm_fpaFDiv(new_pred)) { - return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFDiv_res); - } else if (is_arm_fpaFDiv(new_pred)) { - return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFRdv_res); + if (is_arm_fpaDvf(new_pred) || is_arm_fpaDvf_i(new_pred)) { + return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaDvf_res); + } else if (is_arm_fpaRdf(new_pred) || is_arm_fpaRdf_i(new_pred)) { + return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaRdf_res); + } else if (is_arm_fpaFdv(new_pred) || is_arm_fpaFdv_i(new_pred)) { + return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFdv_res); + } else if (is_arm_fpaFrd(new_pred) || is_arm_fpaFrd_i(new_pred)) { + return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFrd_res); } break; default: break; } - assert(0); - return new_rd_Unknown(irg, mode); + panic("Unsupported Proj from Quot"); } /** - * Transform the Projs of an AddSP. + * Transform the Projs of a be_AddSP. */ static ir_node *gen_Proj_be_AddSP(ir_node *node) { ir_node *block = be_transform_node(get_nodes_block(node)); @@ -1336,20 +1397,22 @@ static ir_node *gen_Proj_be_AddSP(ir_node *node) { dbg_info *dbgi = get_irn_dbg_info(node); long proj = get_Proj_proj(node); - if (proj == pn_be_AddSP_res) { - ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_arm_AddSP_stack); - arch_set_irn_register(env_cg->arch_env, res, &arm_gp_regs[REG_SP]); + if (proj == pn_be_AddSP_sp) { + ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, + pn_arm_SubSPandCopy_stack); + arch_set_irn_register(res, &arm_gp_regs[REG_SP]); return res; + } else if(proj == pn_be_AddSP_res) { + return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, + pn_arm_SubSPandCopy_addr); } else if (proj == pn_be_AddSP_M) { - return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_AddSP_M); + return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_SubSPandCopy_M); } - - assert(0); - return new_rd_Unknown(irg, get_irn_mode(node)); + panic("Unsupported Proj from AddSP"); } /** - * Transform the Projs of a SubSP. + * Transform the Projs of a be_SubSP. */ static ir_node *gen_Proj_be_SubSP(ir_node *node) { ir_node *block = be_transform_node(get_nodes_block(node)); @@ -1359,16 +1422,15 @@ static ir_node *gen_Proj_be_SubSP(ir_node *node) { dbg_info *dbgi = get_irn_dbg_info(node); long proj = get_Proj_proj(node); - if (proj == pn_be_SubSP_res) { - ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_arm_SubSP_stack); - arch_set_irn_register(env_cg->arch_env, res, &arm_gp_regs[REG_SP]); + if (proj == pn_be_SubSP_sp) { + ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, + pn_arm_AddSP_stack); + arch_set_irn_register(res, &arm_gp_regs[REG_SP]); return res; } else if (proj == pn_be_SubSP_M) { - return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_SubSP_M); + return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_AddSP_M); } - - assert(0); - return new_rd_Unknown(irg, get_irn_mode(node)); + panic("Unsupported Proj from SubSP"); } /** @@ -1376,7 +1438,7 @@ static ir_node *gen_Proj_be_SubSP(ir_node *node) { */ static ir_node *gen_Proj_Cmp(ir_node *node) { (void) node; - panic("Psi NYI\n"); + panic("Mux NYI"); } @@ -1400,14 +1462,13 @@ static ir_node *gen_Proj(ir_node *node) { ir_node *pred = get_Proj_pred(node); long proj = get_Proj_proj(node); - if (is_Store(pred) || be_is_FrameStore(pred)) { + if (is_Store(pred)) { if (proj == pn_Store_M) { return be_transform_node(pred); } else { - assert(0); - return new_r_Bad(irg); + panic("Unsupported Proj from Store"); } - } else if (is_Load(pred) || be_is_FrameLoad(pred)) { + } else if (is_Load(pred)) { return gen_Proj_Load(node); } else if (is_CopyB(pred)) { return gen_Proj_CopyB(node); @@ -1419,7 +1480,7 @@ static ir_node *gen_Proj(ir_node *node) { return gen_Proj_be_AddSP(node); } else if (is_Cmp(pred)) { return gen_Proj_Cmp(node); - } else if (get_irn_op(pred) == op_Start) { + } else if (is_Start(pred)) { if (proj == pn_Start_X_initial_exec) { ir_node *block = get_nodes_block(pred); ir_node *jump; @@ -1427,10 +1488,9 @@ static ir_node *gen_Proj(ir_node *node) { /* we exchange the ProjX with a jump */ block = be_transform_node(block); jump = new_rd_Jmp(dbgi, irg, block); - ir_fprintf(stderr, "created jump: %+F\n", jump); return jump; } - if (node == be_get_old_anchor(anchor_tls)) { + if (node == get_irg_anchor(irg, anchor_tls)) { return gen_Proj_tls(node); } } else { @@ -1450,29 +1510,56 @@ static ir_node *gen_Proj(ir_node *node) { return be_duplicate_node(node); } +typedef ir_node *(*create_const_node_func)(dbg_info *db, ir_graph *irg, ir_node *block); + +static INLINE ir_node *create_const(ir_node **place, + create_const_node_func func, + const arch_register_t* reg) +{ + ir_node *block, *res; + + if (*place != NULL) + return *place; + + block = get_irg_start_block(env_cg->irg); + res = func(NULL, env_cg->irg, block); + arch_set_irn_register(res, reg); + *place = res; + + add_irn_dep(get_irg_end(env_cg->irg), res); + return res; +} + +static ir_node *arm_new_Unknown_gp(void) { + return create_const(&env_cg->unknown_gp, new_rd_arm_Unknown_GP, + &arm_gp_regs[REG_GP_UKNWN]); +} + +static ir_node *arm_new_Unknown_fpa(void) { + return create_const(&env_cg->unknown_fpa, new_rd_arm_Unknown_FPA, + &arm_fpa_regs[REG_FPA_UKNWN]); +} + /** * This function just sets the register for the Unknown node * as this is not done during register allocation because Unknown * is an "ignore" node. */ static ir_node *gen_Unknown(ir_node *node) { - (void) node; - /* ir_mode *mode = get_irn_mode(node); if (mode_is_float(mode)) { if (USE_FPA(env_cg->isa)) - return arm_new_Unknown_fpa(env_cg); + return arm_new_Unknown_fpa(); else if (USE_VFP(env_cg->isa)) - return arm_new_Unknown_vfp(env_cg); + panic("VFP not supported yet"); else panic("Softfloat not supported yet"); } else if (mode_needs_gp_reg(mode)) { - return ia32_new_Unknown_gp(env_cg); + return arm_new_Unknown_gp(); } else { assert(0 && "unsupported Unknown-Mode"); } -*/ - panic("Unknown NYI\n"); + return NULL; } @@ -1499,7 +1586,6 @@ static ir_node *gen_Phi(ir_node *node) { copy_node_attr(node, phi); be_duplicate_deps(node, phi); - be_set_transformed_node(node, phi); be_enqueue_preds(node); return phi; @@ -1519,7 +1605,7 @@ static ir_node *gen_Phi(ir_node *node) { * the BAD transformer. */ static ir_node *bad_transform(ir_node *irn) { - panic("ARM backend: Not implemented: %+F\n", irn); + panic("ARM backend: Not implemented: %+F", irn); return irn; } @@ -1552,7 +1638,7 @@ static void arm_register_transformers(void) { GEN(Shl); GEN(Shr); GEN(Shrs); - BAD(Rot); /* unsupported yet */ + GEN(Rotl); GEN(Quot); @@ -1572,8 +1658,7 @@ static void arm_register_transformers(void) { BAD(ASM); /* unsupported yet */ GEN(CopyB); - BAD(Mux); - BAD(Psi); /* unsupported yet */ + BAD(Mux); /* unsupported yet */ GEN(Proj); GEN(Phi); @@ -1599,9 +1684,6 @@ static void arm_register_transformers(void) { GEN(be_FrameAddr); //GEN(be_Call); //GEN(be_Return); - BAD(be_FrameLoad); /* unsupported yet */ - BAD(be_FrameStore); /* unsupported yet */ - BAD(be_StackParam); /* unsupported yet */ GEN(be_AddSP); GEN(be_SubSP); GEN(be_Copy); @@ -1624,20 +1706,62 @@ static void arm_register_transformers(void) { } /** - * Pre-transform all unknown and noreg nodes. + * Pre-transform all unknown nodes. + */ +static void arm_pretransform_node(void) +{ + arm_code_gen_t *cg = env_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_pretransform_node(void *arch_cg) { - arm_code_gen_t *cg = arch_cg; - (void) cg; +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; + } arm_register_transformers(); env_cg = cg; - be_transform_graph(cg->birg, /*arm_pretransform_node*/ NULL, cg); + be_transform_graph(cg->birg, arm_pretransform_node); } void arm_init_transform(void) {