From: Hannes Rapp Date: Wed, 16 Jun 2010 13:28:33 +0000 (+0000) Subject: - restliche ops implementiert: div, mod, and, or etc X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=36a16c275005b032e346f934047c2de8fdb3811f;p=libfirm - restliche ops implementiert: div, mod, and, or etc - optest.c kompiliert [r27627] --- diff --git a/ir/be/sparc/bearch_sparc.c b/ir/be/sparc/bearch_sparc.c index e78adc283..901b86ef0 100644 --- a/ir/be/sparc/bearch_sparc.c +++ b/ir/be/sparc/bearch_sparc.c @@ -345,6 +345,79 @@ static sparc_isa_t sparc_isa_template = { NULL /* current code generator */ }; + +static void sparc_handle_intrinsics(void) +{ + ir_type *tp, *int_tp, *uint_tp; + i_record records[8]; + int n_records = 0; + + runtime_rt rt_iMod, rt_uMod; + +#define ID(x) new_id_from_chars(x, sizeof(x)-1) + + int_tp = new_type_primitive(mode_Is); + uint_tp = new_type_primitive(mode_Iu); + + + /* SPARC has no signed mod instruction ... */ + { + i_instr_record *map_Mod = &records[n_records++].i_instr; + + tp = new_type_method(2, 1); + set_method_param_type(tp, 0, int_tp); + set_method_param_type(tp, 1, int_tp); + set_method_res_type(tp, 0, int_tp); + + rt_iMod.ent = new_entity(get_glob_type(), ID(".rem"), tp); + set_entity_ld_ident(rt_iMod.ent, ID(".rem")); + rt_iMod.mode = mode_T; + rt_iMod.res_mode = mode_Is; + rt_iMod.mem_proj_nr = pn_Mod_M; + rt_iMod.regular_proj_nr = pn_Mod_X_regular; + rt_iMod.exc_proj_nr = pn_Mod_X_except; + rt_iMod.exc_mem_proj_nr = pn_Mod_M; + rt_iMod.res_proj_nr = pn_Mod_res; + + set_entity_visibility(rt_iMod.ent, ir_visibility_external); + + map_Mod->kind = INTRINSIC_INSTR; + map_Mod->op = op_Mod; + map_Mod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall; + map_Mod->ctx = &rt_iMod; + } + /* ... nor an unsigned mod. */ + { + i_instr_record *map_Mod = &records[n_records++].i_instr; + + tp = new_type_method(2, 1); + set_method_param_type(tp, 0, uint_tp); + set_method_param_type(tp, 1, uint_tp); + set_method_res_type(tp, 0, uint_tp); + + rt_uMod.ent = new_entity(get_glob_type(), ID(".urem"), tp); + set_entity_ld_ident(rt_uMod.ent, ID(".urem")); + rt_uMod.mode = mode_T; + rt_uMod.res_mode = mode_Iu; + rt_uMod.mem_proj_nr = pn_Mod_M; + rt_uMod.regular_proj_nr = pn_Mod_X_regular; + rt_uMod.exc_proj_nr = pn_Mod_X_except; + rt_uMod.exc_mem_proj_nr = pn_Mod_M; + rt_uMod.res_proj_nr = pn_Mod_res; + + set_entity_visibility(rt_uMod.ent, ir_visibility_external); + + map_Mod->kind = INTRINSIC_INSTR; + map_Mod->op = op_Mod; + map_Mod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall; + map_Mod->ctx = &rt_uMod; + } + + if (n_records > 0) + lower_intrinsics(records, n_records, /*part_block_used=*/0); +} + + /** * Initializes the backend ISA */ @@ -364,6 +437,7 @@ static arch_env_t *sparc_init(FILE *outfile) sparc_register_init(); sparc_create_opcodes(&sparc_irn_ops); + sparc_handle_intrinsics(); return &isa->arch_env; } diff --git a/ir/be/sparc/bearch_sparc_t.h b/ir/be/sparc/bearch_sparc_t.h index 8240ef03c..3afee30d6 100644 --- a/ir/be/sparc/bearch_sparc_t.h +++ b/ir/be/sparc/bearch_sparc_t.h @@ -34,7 +34,7 @@ // sparc ABI requires a min stacksize to // save registers in case of a trap etc. // by now we assume only non-leaf procedures: 92 + 4 (padding) -#define SPARC_MIN_STACKSIZE 96 +#define SPARC_MIN_STACKSIZE 112 typedef struct sparc_transform_env_t sparc_transform_env_t; typedef struct _sparc_isa_t sparc_isa_t; diff --git a/ir/be/sparc/sparc_emitter.c b/ir/be/sparc/sparc_emitter.c index 3951c21b9..a0c337913 100644 --- a/ir/be/sparc/sparc_emitter.c +++ b/ir/be/sparc/sparc_emitter.c @@ -320,6 +320,7 @@ static void emit_sparc_LoImm(const ir_node *irn) static void emit_be_Return(const ir_node *irn) { be_emit_cstring("\tret"); + //be_emit_cstring("\tjmp %i7+8"); be_emit_finish_line_gas(irn); be_emit_cstring("\trestore"); be_emit_finish_line_gas(irn); @@ -335,6 +336,7 @@ static void emit_be_Call(const ir_node *irn) if (entity != NULL) { be_emit_cstring("\tcall "); sparc_emit_entity(entity); + be_emit_cstring(", 0"); be_emit_finish_line_gas(irn); be_emit_cstring("\tnop"); be_emit_pad_comment(); diff --git a/ir/be/sparc/sparc_new_nodes.c b/ir/be/sparc/sparc_new_nodes.c index dc92b5035..666e6b4e0 100644 --- a/ir/be/sparc/sparc_new_nodes.c +++ b/ir/be/sparc/sparc_new_nodes.c @@ -79,7 +79,7 @@ static int sparc_dump_node(ir_node *n, FILE *F, dump_reason_t reason) /* TODO: dump some attributes which should show up */ /* in node name in dump (e.g. consts or the like) */ - fputs("\n", F); + //fputs("\n", F); if (is_sparc_FrameAddr(n)) { const sparc_symconst_attr_t *attr = get_sparc_symconst_attr_const(n); diff --git a/ir/be/sparc/sparc_spec.pl b/ir/be/sparc/sparc_spec.pl index 2267fcf34..650377bb9 100644 --- a/ir/be/sparc/sparc_spec.pl +++ b/ir/be/sparc/sparc_spec.pl @@ -536,7 +536,7 @@ ShiftLR => { comment => "construct shift logical right", mode => $mode_gp, reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. slr %S1, %R2I, %D1', + emit => '. srl %S1, %R2I, %D1', constructors => \%binop_operand_constructors, }, @@ -587,7 +587,8 @@ UMul => { UDiv => { irn_flags => "R", - mode => $mode_gp, + state => "exc_pinned", +# mode => $mode_gp, comment => "construct Div: Div(a, b) = a / b", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, outs => [ "res" ], diff --git a/ir/be/sparc/sparc_transform.c b/ir/be/sparc/sparc_transform.c index 9cb0f032a..8812f8fdc 100644 --- a/ir/be/sparc/sparc_transform.c +++ b/ir/be/sparc/sparc_transform.c @@ -62,6 +62,69 @@ static inline int mode_needs_gp_reg(ir_mode *mode) return mode_is_int(mode) || mode_is_reference(mode); } +/** + * Create an And that will zero out upper bits. + * + * @param dbgi debug info + * @param block the basic block + * @param op the original node + * @param src_bits number of lower bits that will remain + */ +static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op, + int src_bits) +{ + if (src_bits == 8) { + return new_bd_sparc_And_imm(dbgi, block, op, 0xFF); + } else if (src_bits == 16) { + ir_node *lshift = new_bd_sparc_ShiftLL_imm(dbgi, block, op, 16); + ir_node *rshift = new_bd_sparc_ShiftLR_imm(dbgi, block, lshift, 16); + return rshift; + } else { + panic("zero extension only supported for 8 and 16 bits"); + } +} + +/** + * Generate code for a sign extension. + */ +static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op, + int src_bits) +{ + int shift_width = 32 - src_bits; + ir_node *lshift_node = new_bd_sparc_ShiftLL_imm(dbgi, block, op, shift_width); + ir_node *rshift_node = new_bd_sparc_ShiftRA_imm(dbgi, block, lshift_node, shift_width); + return rshift_node; +} + +/** + * returns true if it is assured, that the upper bits of a node are "clean" + * which means for a 16 or 8 bit value, that the upper bits in the register + * are 0 for unsigned and a copy of the last significant bit for signed + * numbers. + */ +static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode) +{ + (void) transformed_node; + (void) mode; + /* TODO */ + return false; +} + +static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op, + ir_mode *orig_mode) +{ + int bits = get_mode_size_bits(orig_mode); + if (bits == 32) + return op; + + if (mode_is_signed(orig_mode)) { + return gen_sign_extension(dbgi, block, op, bits); + } else { + return gen_zero_extension(dbgi, block, op, bits); + } +} + + /** * Creates a possible DAG for a constant. */ @@ -274,11 +337,11 @@ static ir_node *gen_Store(ir_node *node) /** * Creates an sparc Mul. + * returns the lower 32bits of the 64bit multiply result * * @return the created sparc Mul node */ -static ir_node *gen_Mul(ir_node *node) -{ +static ir_node *gen_Mul(ir_node *node) { ir_mode *mode = get_irn_mode(node); dbg_info *dbgi = get_irn_dbg_info(node); @@ -291,11 +354,36 @@ static ir_node *gen_Mul(ir_node *node) assert(mode_is_data(mode)); mul = gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_UMul_reg, new_bd_sparc_UMul_imm); + arch_irn_add_flags(mul, arch_irn_flags_modify_flags); proj_res_low = new_rd_Proj(dbgi, mul, mode_Iu, pn_sparc_UMul_low); return proj_res_low; +} + +/** + * Creates an sparc Mulh. + * Mulh returns the upper 32bits of a mul instruction + * + * @return the created sparc Mulh node + */ +static ir_node *gen_Mulh(ir_node *node) { + ir_mode *mode = get_irn_mode(node); + dbg_info *dbgi = get_irn_dbg_info(node); + + ir_node *mul; + ir_node *proj_res_hi; + + if (mode_is_float(mode)) + panic("FP not supported yet"); + + + assert(mode_is_data(mode)); + mul = gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_UMul_reg, new_bd_sparc_UMul_imm); + arch_irn_add_flags(mul, arch_irn_flags_modify_flags); - //return gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_Mul_reg, new_bd_sparc_Mul_imm); + proj_res_hi = new_rd_Proj(dbgi, mul, mode_Iu, pn_sparc_UMul_low); // TODO: this actually should be pn_sparc_UMul_high ! + //arch_set_irn_register(proj_res_hi, &sparc_flags_regs[REG_Y]); + return proj_res_hi; } /** @@ -303,24 +391,21 @@ static ir_node *gen_Mul(ir_node *node) * * @return the created sparc Div node */ -static ir_node *gen_Div(ir_node *node) -{ +static ir_node *gen_Div(ir_node *node) { + ir_mode *mode = get_irn_mode(node); - //dbg_info *dbgi = get_irn_dbg_info(node); - //ir_node *proj_res_low; + ir_node *div; if (mode_is_float(mode)) panic("FP not supported yet"); - return gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_UDiv_reg, new_bd_sparc_UDiv_imm); - - //proj_res = new_rd_Proj(dbgi, mul, mode_Iu, pn_sparc_UDiv_res); - //return proj_res; - - //return gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_Mul_reg, new_bd_sparc_Mul_imm); + //assert(mode_is_data(mode)); + div = gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_UDiv_reg, new_bd_sparc_UDiv_imm); + return div; } + /** * transform abs node: * mov a, b @@ -330,8 +415,7 @@ static ir_node *gen_Div(ir_node *node) * * @return */ -static ir_node *gen_Abs(ir_node *node) -{ +static ir_node *gen_Abs(ir_node *node) { ir_node *block = be_transform_node(get_nodes_block(node)); ir_mode *mode = get_irn_mode(node); dbg_info *dbgi = get_irn_dbg_info(node); @@ -367,6 +451,36 @@ static ir_node *gen_Not(ir_node *node) return new_bd_sparc_Not(dbgi, block, new_op); } +static ir_node *gen_And(ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + dbg_info *dbgi = get_irn_dbg_info(node); + + (void) block; + (void) dbgi; + + if (mode_is_float(mode)) + panic("FP not implemented yet"); + + return gen_helper_binop(node, MATCH_COMMUTATIVE, new_bd_sparc_And_reg, new_bd_sparc_And_imm); +} + +static ir_node *gen_Or(ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + dbg_info *dbgi = get_irn_dbg_info(node); + + (void) block; + (void) dbgi; + + if (mode_is_float(mode)) + panic("FP not implemented yet"); + + return gen_helper_binop(node, MATCH_COMMUTATIVE, new_bd_sparc_Or_reg, new_bd_sparc_Or_imm); +} + static ir_node *gen_Shl(ir_node *node) { return gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_ShiftLL_reg, new_bd_sparc_ShiftLL_imm); @@ -377,6 +491,11 @@ static ir_node *gen_Shr(ir_node *node) return gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_ShiftLR_reg, new_bd_sparc_ShiftLR_imm); } +static ir_node *gen_Shra(ir_node *node) +{ + return gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_ShiftRA_reg, new_bd_sparc_ShiftRA_imm); +} + /****** TRANSFORM GENERAL BACKEND NODES ********/ /** @@ -593,9 +712,11 @@ static ir_node *gen_Cmp(ir_node *node) panic("FloatCmp not implemented"); } + /* if (get_mode_size_bits(cmp_mode) != 32) { panic("CmpMode != 32bit not supported yet"); } + */ assert(get_irn_mode(op2) == cmp_mode); is_unsigned = !mode_is_signed(cmp_mode); @@ -617,9 +738,9 @@ static ir_node *gen_Cmp(ir_node *node) /* integer compare */ new_op1 = be_transform_node(op1); - //new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode); + new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode); new_op2 = be_transform_node(op2); - //new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode); + new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode); return new_bd_sparc_Cmp_reg(dbgi, block, new_op1, new_op2, false, is_unsigned); } @@ -638,54 +759,6 @@ static ir_node *gen_SymConst(ir_node *node) return new_node; } -/** - * Create an And that will zero out upper bits. - * - * @param dbgi debug info - * @param block the basic block - * @param op the original node - * @param src_bits number of lower bits that will remain - */ -static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op, - int src_bits) -{ - if (src_bits == 8) { - return new_bd_sparc_And_imm(dbgi, block, op, 0xFF); - } else if (src_bits == 16) { - ir_node *lshift = new_bd_sparc_ShiftLL_imm(dbgi, block, op, 16); - ir_node *rshift = new_bd_sparc_ShiftLR_imm(dbgi, block, lshift, 16); - return rshift; - } else { - panic("zero extension only supported for 8 and 16 bits"); - } -} - -/** - * Generate code for a sign extension. - */ -static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op, - int src_bits) -{ - int shift_width = 32 - src_bits; - ir_node *lshift_node = new_bd_sparc_ShiftLL_imm(dbgi, block, op, shift_width); - ir_node *rshift_node = new_bd_sparc_ShiftRA_imm(dbgi, block, lshift_node, shift_width); - return rshift_node; -} - -/** - * returns true if it is assured, that the upper bits of a node are "clean" - * which means for a 16 or 8 bit value, that the upper bits in the register - * are 0 for unsigned and a copy of the last significant bit for signed - * numbers. - */ -static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode) -{ - (void) transformed_node; - (void) mode; - /* TODO */ - return false; -} - /** * Transforms a Conv node. * @@ -830,13 +903,11 @@ static ir_node *gen_Proj_be_AddSP(ir_node *node) long proj = get_Proj_proj(node); if (proj == pn_be_AddSP_sp) { - // TODO: check for correct pn_sparc_* flags ir_node *res = new_rd_Proj(dbgi, new_pred, mode_Iu, pn_sparc_SubSP_stack); arch_set_irn_register(res, &sparc_gp_regs[REG_SP]); return res; } else if (proj == pn_be_AddSP_res) { - // TODO: check for correct pn_sparc_* flags return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_sparc_SubSP_stack); } else if (proj == pn_be_AddSP_M) { return new_rd_Proj(dbgi, new_pred, mode_M, pn_sparc_SubSP_M); @@ -877,6 +948,27 @@ static ir_node *gen_Proj_Cmp(ir_node *node) } +static ir_node *gen_Proj_Div(ir_node *node) +{ + ir_node *pred = get_Proj_pred(node); + ir_node *new_pred = be_transform_node(pred); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_mode *mode = get_irn_mode(node); + long proj = get_Proj_proj(node); + + switch (proj) { + case pn_Div_res: + if (is_sparc_UDiv(new_pred)) { + return new_rd_Proj(dbgi, new_pred, mode, pn_sparc_UDiv_res); + } + break; + default: + break; + } + panic("Unsupported Proj from Div"); +} + + /** * Transform a Proj node. */ @@ -907,6 +999,8 @@ static ir_node *gen_Proj(ir_node *node) } else if (is_Cmp(pred)) { //panic("gen_Proj not implemented for Cmp"); return gen_Proj_Cmp(node); + } else if (is_Div(pred)) { + return gen_Proj_Div(node); } else if (is_Start(pred)) { /* if (proj == pn_Start_X_initial_exec) { @@ -995,26 +1089,27 @@ void sparc_register_transformers(void) set_transformer(op_Jmp, gen_Jmp); set_transformer(op_Mul, gen_Mul); + set_transformer(op_Mulh, gen_Mulh); set_transformer(op_Div, gen_Div); set_transformer(op_Abs, gen_Abs); set_transformer(op_Shl, gen_Shl); set_transformer(op_Shr, gen_Shr); + set_transformer(op_Shrs, gen_Shra); set_transformer(op_Minus, gen_Minus); set_transformer(op_Not, gen_Not); + set_transformer(op_And, gen_And); + set_transformer(op_Or, gen_Or); set_transformer(op_Unknown, gen_Unknown); /* node list */ /* - set_transformer(op_And, gen_And); + set_transformer(op_CopyB, gen_CopyB); set_transformer(op_Eor, gen_Eor); - set_transformer(op_Mul, gen_Mul); - set_transformer(op_Or, gen_Or); set_transformer(op_Quot, gen_Quot); set_transformer(op_Rotl, gen_Rotl); - set_transformer(op_Shrs, gen_Shrs); */ set_transformer(op_ASM, bad_transform); @@ -1029,7 +1124,7 @@ void sparc_register_transformers(void) set_transformer(op_Free, bad_transform); set_transformer(op_Id, bad_transform); set_transformer(op_InstOf, bad_transform); - set_transformer(op_Mulh, bad_transform); + set_transformer(op_Mux, bad_transform); set_transformer(op_Raise, bad_transform); set_transformer(op_Sel, bad_transform);