From: Hannes Rapp Date: Tue, 13 Jul 2010 11:37:08 +0000 (+0000) Subject: - SPEC gzip laeuft X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=70b9a908fa685eda7842489341e84c1799d393f7;p=libfirm - SPEC gzip laeuft - Code soweit bereinigt [r27734] --- diff --git a/ir/be/sparc/sparc_emitter.c b/ir/be/sparc/sparc_emitter.c index e5883b1d0..338c1daf5 100644 --- a/ir/be/sparc/sparc_emitter.c +++ b/ir/be/sparc/sparc_emitter.c @@ -51,6 +51,8 @@ #include "gen_sparc_emitter.h" #include "sparc_nodes_attr.h" #include "sparc_new_nodes.h" +#include "gen_sparc_regalloc_if.h" + #define SNPRINTF_BUF_LEN 128 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) @@ -129,11 +131,8 @@ static const arch_register_t *get_out_reg(const ir_node *node, int pos) void sparc_emit_immediate(const ir_node *node) { - // TODO: make sure it's a valid simm13 ? const sparc_attr_t *attr = get_sparc_attr_const(node); - assert(!(attr->immediate_value < -4096 || attr->immediate_value > 4096)); - be_emit_irprintf("%d", attr->immediate_value); } @@ -221,6 +220,75 @@ void sparc_emit_store_mode(const ir_node *node) } } +/** + * emit integer signed/unsigned prefix char + */ +void sparc_emit_mode_sign_prefix(const ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); + bool is_signed = mode_is_signed(mode); + be_emit_string(is_signed ? "s" : "u"); +} + +/** + * emit FP load mode char + */ +void sparc_emit_fp_load_mode(const ir_node *node) +{ + const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node); + ir_mode *mode = attr->load_store_mode; + int bits = get_mode_size_bits(mode); + + assert(mode_is_float(mode)); + + if (bits == 32) { + be_emit_string("f"); + } else if (bits == 64) { + be_emit_string("df"); + } else { + panic("FP load mode > 64bits not implemented yet"); + } +} + +/** + * emit FP store mode char + */ +void sparc_emit_fp_store_mode(const ir_node *node) +{ + const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node); + ir_mode *mode = attr->load_store_mode; + int bits = get_mode_size_bits(mode); + + assert(mode_is_float(mode)); + + if (bits == 32) { + be_emit_string("f"); + } else if (bits == 64) { + be_emit_string("df"); + } else { + panic("FP store mode > 64bits not implemented yet"); + } +} + +/** + * emits the FP mode suffix char + */ +void sparc_emit_fp_mode_suffix(const ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); + int bits = get_mode_size_bits(mode); + + assert(mode_is_float(mode)); + + if (bits == 32) { + be_emit_string("s"); + } else if (bits == 64) { + be_emit_string("d"); + } else { + panic("FP mode > 64bits not implemented yet"); + } +} + /** * Returns the target label for a control flow node. */ @@ -275,8 +343,7 @@ static void emit_be_IncSP(const ir_node *irn) } /** - * emits code for save instruction - * and sets the current save_attr pointer + * emits code for save instruction with min. required stack space */ static void emit_sparc_Save(const ir_node *irn) { @@ -313,6 +380,65 @@ static void emit_sparc_LoImm(const ir_node *irn) be_emit_finish_line_gas(irn); } +/** + * emit code for div with the correct sign prefix + */ +static void emit_sparc_Div(const ir_node *irn) +{ + be_emit_cstring("\t"); + sparc_emit_mode_sign_prefix(irn); + be_emit_cstring("div "); + + sparc_emit_source_register(irn, 0); + be_emit_cstring(", "); + sparc_emit_reg_or_imm(irn, 1); + be_emit_cstring(", "); + sparc_emit_dest_register(irn, 0); + be_emit_finish_line_gas(irn); +} + +/** + * emit code for mul with the correct sign prefix + */ +static void emit_sparc_Mul(const ir_node *irn) +{ + be_emit_cstring("\t"); + sparc_emit_mode_sign_prefix(irn); + be_emit_cstring("mul "); + + sparc_emit_source_register(irn, 0); + be_emit_cstring(", "); + sparc_emit_reg_or_imm(irn, 1); + be_emit_cstring(", "); + sparc_emit_dest_register(irn, 0); + be_emit_finish_line_gas(irn); +} + +/** + * emits code for mulh + */ +static void emit_sparc_Mulh(const ir_node *irn) +{ + be_emit_cstring("\t"); + sparc_emit_mode_sign_prefix(irn); + be_emit_cstring("mul "); + + sparc_emit_source_register(irn, 0); + be_emit_cstring(", "); + sparc_emit_reg_or_imm(irn, 1); + be_emit_cstring(", "); + sparc_emit_dest_register(irn, 0); + be_emit_finish_line_gas(irn); + + // our result is in the y register now + // we just copy it to the assigned target reg + be_emit_cstring("\tmov "); + be_emit_char('%'); + be_emit_string(arch_register_get_name(&sparc_flags_regs[REG_Y])); + be_emit_cstring(", "); + sparc_emit_dest_register(irn, 0); + be_emit_finish_line_gas(irn); +} /** * Emits code for return node @@ -350,7 +476,7 @@ static void emit_be_Call(const ir_node *irn) } /** - * TODO: check if this is correct + * Emit code for Perm node */ static void emit_be_Perm(const ir_node *irn) { @@ -379,6 +505,54 @@ static void emit_be_Perm(const ir_node *irn) be_emit_finish_line_gas(irn); } +/** + * TODO: not really tested but seems to work with memperm_arity == 1 + */ +static void emit_be_MemPerm(const ir_node *node) +{ + int i; + int memperm_arity; + int sp_change = 0; + + /* TODO: this implementation is slower than necessary. + The longterm goal is however to avoid the memperm node completely */ + + memperm_arity = be_get_MemPerm_entity_arity(node); + // we use our local registers - so this is limited to 8 inputs ! + if (memperm_arity > 8) + panic("memperm with more than 8 inputs not supported yet"); + + for (i = 0; i < memperm_arity; ++i) { + int offset; + ir_entity *entity = be_get_MemPerm_in_entity(node, i); + + /* spill register */ + sp_change += 4; + be_emit_irprintf("\tst %%l%d, [%%sp-%d]", i, sp_change); + be_emit_finish_line_gas(node); + + /* load from entity */ + offset = get_entity_offset(entity) + sp_change; + be_emit_irprintf("\tld [%%sp+%d], %%l%d", offset, i); + be_emit_finish_line_gas(node); + } + + for (i = memperm_arity-1; i >= 0; --i) { + int offset; + ir_entity *entity = be_get_MemPerm_out_entity(node, i); + + /* store to new entity */ + offset = get_entity_offset(entity) + sp_change; + be_emit_irprintf("\tst %%l%d, [%%sp+%d]", i, offset); + be_emit_finish_line_gas(node); + /* restore register */ + be_emit_irprintf("\tld [%%sp-%d], %%l%d", sp_change, i); + sp_change -= 4; + be_emit_finish_line_gas(node); + } + assert(sp_change == 0); +} + /** * Emit a SymConst. */ @@ -405,7 +579,6 @@ static void emit_sparc_SymConst(const ir_node *irn) be_emit_finish_line_gas(irn); } - /** * Emits code for FrameAddr fix */ @@ -605,22 +778,26 @@ static void sparc_register_emitters(void) sparc_register_spec_emitters(); /* custom emitter */ - set_emitter(op_be_IncSP, emit_be_IncSP); - set_emitter(op_be_Return, emit_be_Return); - set_emitter(op_be_Call, emit_be_Call); - set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr); - set_emitter(op_sparc_Branch, emit_sparc_Branch); - set_emitter(op_sparc_SymConst, emit_sparc_SymConst); - set_emitter(op_sparc_Jmp, emit_sparc_Jmp); - set_emitter(op_sparc_Save, emit_sparc_Save); - - set_emitter(op_sparc_HiImm, emit_sparc_HiImm); - set_emitter(op_sparc_LoImm, emit_sparc_LoImm); - - set_emitter(op_be_Copy, emit_be_Copy); - set_emitter(op_be_CopyKeep, emit_be_Copy); - - set_emitter(op_be_Perm, emit_be_Perm); + set_emitter(op_be_IncSP, emit_be_IncSP); + set_emitter(op_be_Return, emit_be_Return); + set_emitter(op_be_Call, emit_be_Call); + set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr); + set_emitter(op_sparc_Branch, emit_sparc_Branch); + set_emitter(op_sparc_SymConst, emit_sparc_SymConst); + set_emitter(op_sparc_Jmp, emit_sparc_Jmp); + set_emitter(op_sparc_Save, emit_sparc_Save); + + set_emitter(op_sparc_HiImm, emit_sparc_HiImm); + set_emitter(op_sparc_LoImm, emit_sparc_LoImm); + set_emitter(op_sparc_Div, emit_sparc_Div); + set_emitter(op_sparc_Mul, emit_sparc_Mul); + set_emitter(op_sparc_Mulh, emit_sparc_Mulh); + + set_emitter(op_be_Copy, emit_be_Copy); + set_emitter(op_be_CopyKeep, emit_be_Copy); + + set_emitter(op_be_Perm, emit_be_Perm); + set_emitter(op_be_MemPerm, emit_be_MemPerm); /* set_emitter(op_arm_B, emit_arm_B); @@ -629,7 +806,6 @@ static void sparc_register_emitters(void) set_emitter(op_arm_fpaDbl2GP, emit_arm_fpaDbl2GP); set_emitter(op_arm_LdTls, emit_arm_LdTls); set_emitter(op_arm_SwitchJmp, emit_arm_SwitchJmp); - set_emitter(op_be_MemPerm, emit_be_MemPerm); */ /* no need to emit anything for the following nodes */ diff --git a/ir/be/sparc/sparc_emitter.h b/ir/be/sparc/sparc_emitter.h index 0e36800e3..44971cfd8 100644 --- a/ir/be/sparc/sparc_emitter.h +++ b/ir/be/sparc/sparc_emitter.h @@ -45,6 +45,10 @@ void sparc_emit_dest_register(const ir_node *node, int pos); void sparc_emit_offset(const ir_node *node); void sparc_emit_load_mode(const ir_node *node); void sparc_emit_store_mode(const ir_node *node); +void sparc_emit_mode_sign_prefix(const ir_node *node); +void sparc_emit_fp_mode_suffix(const ir_node *node); +void sparc_emit_fp_load_mode(const ir_node *node); +void sparc_emit_fp_store_mode(const ir_node *node); void sparc_gen_routine(const sparc_code_gen_t *cg, ir_graph *irg); diff --git a/ir/be/sparc/sparc_new_nodes.c b/ir/be/sparc/sparc_new_nodes.c index 77139558b..386dd16d3 100644 --- a/ir/be/sparc/sparc_new_nodes.c +++ b/ir/be/sparc/sparc_new_nodes.c @@ -154,8 +154,6 @@ const sparc_attr_t *get_sparc_attr_const(const ir_node *node) return (const sparc_attr_t *)get_irn_generic_attr_const(node); } - - sparc_load_store_attr_t *get_sparc_load_store_attr(ir_node *node) { assert(is_sparc_irn(node) && "need sparc node to get attributes"); diff --git a/ir/be/sparc/sparc_new_nodes.h b/ir/be/sparc/sparc_new_nodes.h index 66615754a..d06b2e187 100644 --- a/ir/be/sparc/sparc_new_nodes.h +++ b/ir/be/sparc/sparc_new_nodes.h @@ -62,7 +62,6 @@ const sparc_cmp_attr_t *get_sparc_cmp_attr_const(const ir_node *node); sparc_save_attr_t *get_sparc_save_attr(ir_node *node); const sparc_save_attr_t *get_sparc_save_attr_const(const ir_node *node); - /** * Returns the argument register requirements of an sparc node. */ diff --git a/ir/be/sparc/sparc_nodes_attr.h b/ir/be/sparc/sparc_nodes_attr.h index fe266abc2..0ebac3c52 100644 --- a/ir/be/sparc/sparc_nodes_attr.h +++ b/ir/be/sparc/sparc_nodes_attr.h @@ -40,6 +40,14 @@ struct sparc_attr_t bool is_load_store; }; +/** + * attribute for FP immediate instruction + */ +typedef struct sparc_fp_attr_t sparc_fp_attr_t; +struct sparc_fp_attr_t { + sparc_attr_t base; /**< generic attribute */ + double fp_immediate; /* the FP immediate value */ +}; /** * attribute for save instruction diff --git a/ir/be/sparc/sparc_spec.pl b/ir/be/sparc/sparc_spec.pl index 650377bb9..78b9fb3ef 100644 --- a/ir/be/sparc/sparc_spec.pl +++ b/ir/be/sparc/sparc_spec.pl @@ -221,6 +221,10 @@ $mode_fp = "mode_D"; C => "${arch}_emit_immediate(node);", LM => "${arch}_emit_load_mode(node);", SM => "${arch}_emit_store_mode(node);", + EXTPREF => "${arch}_emit_mode_sign_prefix(node);", + FPM => "${arch}_emit_fp_mode_suffix(node);", + FPLM => "${arch}_emit_fp_load_mode(node);", + FPSM => "${arch}_emit_fp_store_mode(node);", O => "${arch}_emit_offset(node);", ); @@ -576,16 +580,24 @@ Xor => { constructors => \%binop_operand_constructors, }, -UMul => { +Mul => { state => "exc_pinned", comment => "construct Mul: Mul(a, b) = Mul(b, a) = a * b", reg_req => { in => [ "gp", "gp" ], out => [ "gp", "flags" ] }, outs => [ "low", "high" ], constructors => \%binop_operand_constructors, - emit =>'. umul %S1, %R2I, %D1' +# emit =>'. mul %S1, %R2I, %D1' }, -UDiv => { +Mulh => { + state => "exc_pinned", + comment => "construct Mul: Mul(a, b) = Mul(b, a) = a * b", + reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] }, + outs => [ "low", "high" ], + constructors => \%binop_operand_constructors, +}, + +Div => { irn_flags => "R", state => "exc_pinned", # mode => $mode_gp, @@ -593,7 +605,7 @@ UDiv => { reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, outs => [ "res" ], constructors => \%binop_operand_constructors, - emit =>'. udiv %S1, %R2I, %D1' +# emit =>'. div %S1, %R2I, %D1' }, Minus => { @@ -613,6 +625,12 @@ Not => { emit => '. xnor %S1, %%g0, %D1' }, +Nop => { + op_flags => "K", + reg_req => { in => [], out => [ "none" ] }, + emit => '. nop', +}, + #Mul_i => { # irn_flags => "R", # comment => "construct Mul: Mul(a, const) = Mul(const, a) = a * const", @@ -755,22 +773,71 @@ Not => { # |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ # #--------------------------------------------------------# -# commutative operations +fAdd => { + op_flags => "C", + irn_flags => "R", + comment => "construct FP Add: Add(a, b) = Add(b, a) = a + b", + reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, + emit => '. fadd%FPM %S1, %S2, %D1' +}, + +fMul => { + op_flags => "C", + comment => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b", + reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, + emit =>'. fmul%FPM %S1, %S2, %D1' +}, + +fsMuld => { + op_flags => "C", + comment => "construct FP single to double precision Mul: Mul(a, b) = Mul(b, a) = a * b", + reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, + emit =>'. fsmuld %S1, %S2, %D1' +}, + +FpSToFpD => { + irn_flags => "R", + comment => "convert FP (single) to FP (double)", + reg_req => { in => [ "fp" ], out => [ "fp" ] }, + emit =>'. FsTOd %S1, %D1' +}, + +FpDToFpS => { + irn_flags => "R", + comment => "convert FP (double) to FP (single)", + reg_req => { in => [ "fp" ], out => [ "fp" ] }, + emit =>'. FdTOs %S1, %D1' +}, + +FpSToInt => { + irn_flags => "R", + comment => "convert integer to FP", + reg_req => { in => [ "fp" ], out => [ "gp" ] }, + emit =>'. FiTOs %S1, %D1' +}, + +FpDToInt => { + irn_flags => "R", + comment => "convert integer to FP", + reg_req => { in => [ "fp" ], out => [ "gp" ] }, + emit =>'. FiTOd %S1, %D1' +}, + +IntToFpS => { + irn_flags => "R", + comment => "convert FP (single) to integer", + reg_req => { in => [ "gp" ], out => [ "fp" ] }, + emit =>'. FsTOi %S1, %D1' +}, + +IntToFpD => { + irn_flags => "R", + comment => "convert FP (double) to integer", + reg_req => { in => [ "gp" ], out => [ "fp" ] }, + emit =>'. FdTOi %S1, %D1' +}, + -#fAdd => { -# op_flags => "C", -# irn_flags => "R", -# comment => "construct FP Add: Add(a, b) = Add(b, a) = a + b", -# reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, -# emit => '. fadd %S1, %S2, %D1' -#}, -# -#fMul => { -# op_flags => "C", -# comment => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b", -# reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, -# emit =>'. fmul %S1, %S2, %D1' -#}, # #fMax => { # op_flags => "C", diff --git a/ir/be/sparc/sparc_transform.c b/ir/be/sparc/sparc_transform.c index c602ad8d5..2ca1b0a9e 100644 --- a/ir/be/sparc/sparc_transform.c +++ b/ir/be/sparc/sparc_transform.c @@ -57,6 +57,9 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) static sparc_code_gen_t *env_cg; +static ir_node *gen_SymConst(ir_node *node); + + static inline int mode_needs_gp_reg(ir_mode *mode) { return mode_is_int(mode) || mode_is_reference(mode); @@ -170,6 +173,15 @@ static ir_node *create_const_graph(ir_node *irn, ir_node *block) return create_const_graph_value(dbgi, block, value); } +/** + * create a DAG to load fp constant. sparc only supports loading from global memory + */ +static ir_node *create_fp_const_graph(ir_node *irn, ir_node *block) +{ + (void) block; + panic("FP constants not implemented"); +} + typedef enum { MATCH_NONE = 0, @@ -178,6 +190,7 @@ typedef enum { } match_flags_t; typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2); +typedef ir_node* (*new_binop_fp_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode); typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, int simm13); /** @@ -188,6 +201,8 @@ static bool is_imm_encodeable(const ir_node *node) { long val; + //assert(mode_is_float_vector(get_irn_mode(node))); + if (!is_Const(node)) return false; @@ -236,6 +251,23 @@ static ir_node *gen_helper_binop(ir_node *node, match_flags_t flags, return new_reg(dbgi, block, new_op1, new_op2); } +/** + * helper function for FP binop operations + */ +static ir_node *gen_helper_binfpop(ir_node *node, new_binop_fp_func new_reg) +{ + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op1 = get_binop_left(node); + ir_node *new_op1; + ir_node *op2 = get_binop_right(node); + ir_node *new_op2; + dbg_info *dbgi = get_irn_dbg_info(node); + + new_op2 = be_transform_node(op2); + new_op1 = be_transform_node(op1); + return new_reg(dbgi, block, new_op1, new_op2, get_irn_mode(node)); +} + /** * Creates an sparc Add. * @@ -348,15 +380,16 @@ static ir_node *gen_Mul(ir_node *node) { ir_node *mul; ir_node *proj_res_low; - if (mode_is_float(mode)) - panic("FP not supported yet"); - + if (mode_is_float(mode)) { + mul = gen_helper_binfpop(node, new_bd_sparc_fMul); + return mul; + } 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); + mul = gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_Mul_reg, new_bd_sparc_Mul_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); + proj_res_low = new_rd_Proj(dbgi, mul, mode_Iu, pn_sparc_Mul_low); return proj_res_low; } @@ -378,11 +411,9 @@ static ir_node *gen_Mulh(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_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]); + mul = gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_Mulh_reg, new_bd_sparc_Mulh_imm); + //arch_irn_add_flags(mul, arch_irn_flags_modify_flags); + proj_res_hi = new_rd_Proj(dbgi, mul, mode_Iu, pn_sparc_Mulh_low); return proj_res_hi; } @@ -401,7 +432,7 @@ static ir_node *gen_Div(ir_node *node) { panic("FP not supported yet"); //assert(mode_is_data(mode)); - div = gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_UDiv_reg, new_bd_sparc_UDiv_imm); + div = gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_Div_reg, new_bd_sparc_Div_imm); return div; } @@ -481,6 +512,21 @@ static ir_node *gen_Or(ir_node *node) return gen_helper_binop(node, MATCH_COMMUTATIVE, new_bd_sparc_Or_reg, new_bd_sparc_Or_imm); } +static ir_node *gen_Xor(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_Xor_reg, new_bd_sparc_Xor_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); @@ -521,7 +567,7 @@ static ir_node *gen_Minus(ir_node *node) /** * Transforms a Const node. * - * @param node the ir Store node + * @param node the ir Const node * @return The transformed sparc node. */ static ir_node *gen_Const(ir_node *node) @@ -533,8 +579,9 @@ static ir_node *gen_Const(ir_node *node) (void) dbg; if (mode_is_float(mode)) { - panic("FP not supported yet"); + return create_fp_const_graph(node, block); } + return create_const_graph(node, block); } @@ -772,14 +819,46 @@ static ir_node *gen_Conv(ir_node *node) ir_mode *dst_mode = get_irn_mode(node); dbg_info *dbg = get_irn_dbg_info(node); + int src_bits = get_mode_size_bits(src_mode); + int dst_bits = get_mode_size_bits(dst_mode); + if (src_mode == dst_mode) return new_op; if (mode_is_float(src_mode) || mode_is_float(dst_mode)) { - panic("FP not implemented"); + assert((src_bits <= 64 && dst_bits <= 64) && "quad FP not implemented"); + + if (mode_is_float(src_mode)) { + if (mode_is_float(dst_mode)) { + // float -> float conv + if (src_bits > dst_bits) { + return new_bd_sparc_FpDToFpS(dbg, block, new_op, dst_mode); + } else { + return new_bd_sparc_FpSToFpD(dbg, block, new_op, dst_mode); + } + } else { + // float -> int conv + switch (dst_bits) { + case 32: + return new_bd_sparc_FpSToInt(dbg, block, new_op, dst_mode); + case 64: + return new_bd_sparc_FpDToInt(dbg, block, new_op, dst_mode); + default: + panic("quad FP not implemented"); + } + } + } else { + // int -> float conv + switch (dst_bits) { + case 32: + return new_bd_sparc_IntToFpS(dbg, block, new_op, src_mode); + case 64: + return new_bd_sparc_IntToFpD(dbg, block, new_op, src_mode); + default: + panic("quad FP not implemented"); + } + } } else { /* complete in gp registers */ - int src_bits = get_mode_size_bits(src_mode); - int dst_bits = get_mode_size_bits(dst_mode); int min_bits; ir_mode *min_mode; @@ -947,7 +1026,9 @@ static ir_node *gen_Proj_Cmp(ir_node *node) panic("not implemented"); } - +/** + * transform Projs from a Div + */ static ir_node *gen_Proj_Div(ir_node *node) { ir_node *pred = get_Proj_pred(node); @@ -958,8 +1039,8 @@ static ir_node *gen_Proj_Div(ir_node *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); + if (is_sparc_Div(new_pred)) { + return new_rd_Proj(dbgi, new_pred, mode, pn_sparc_Div_res); } break; default: @@ -1044,58 +1125,103 @@ static ir_node *gen_Jmp(ir_node *node) } /** - * configure transformation callbacks + * the BAD transformer. */ -void sparc_register_transformers(void) +static ir_node *bad_transform(ir_node *irn) { - be_start_transform_setup(); - - be_set_transform_function(op_Add, gen_Add); - be_set_transform_function(op_Store, gen_Store); - be_set_transform_function(op_Const, gen_Const); - be_set_transform_function(op_Load, gen_Load); - be_set_transform_function(op_Sub, gen_Sub); - - be_set_transform_function(op_be_AddSP, gen_be_AddSP); - be_set_transform_function(op_be_SubSP, gen_be_SubSP); - be_set_transform_function(op_be_Copy, gen_be_Copy); - be_set_transform_function(op_be_Call, gen_be_Call); - be_set_transform_function(op_be_FrameAddr, gen_be_FrameAddr); - - be_set_transform_function(op_Cond, gen_Cond); - be_set_transform_function(op_Cmp, gen_Cmp); - - be_set_transform_function(op_SymConst, gen_SymConst); - - be_set_transform_function(op_Phi, gen_Phi); - be_set_transform_function(op_Proj, gen_Proj); - - be_set_transform_function(op_Conv, gen_Conv); - be_set_transform_function(op_Jmp, gen_Jmp); - - be_set_transform_function(op_Mul, gen_Mul); - be_set_transform_function(op_Mulh, gen_Mulh); - be_set_transform_function(op_Div, gen_Div); - be_set_transform_function(op_Abs, gen_Abs); - be_set_transform_function(op_Shl, gen_Shl); - be_set_transform_function(op_Shr, gen_Shr); - be_set_transform_function(op_Shrs, gen_Shra); + panic("SPARC backend: Not implemented: %+F", irn); +} - be_set_transform_function(op_Minus, gen_Minus); - be_set_transform_function(op_Not, gen_Not); - be_set_transform_function(op_And, gen_And); - be_set_transform_function(op_Or, gen_Or); +/** + * Set a node emitter. Make it a bit more type safe. + */ +static void set_transformer(ir_op *op, be_transform_func sparc_transform_func) +{ + op->ops.generic = (op_func)sparc_transform_func; +} - be_set_transform_function(op_Unknown, gen_Unknown); +/** + * configure transformation callbacks + */ +void sparc_register_transformers(void) +{ + clear_irp_opcodes_generic_func(); + set_transformer(op_Add, gen_Add); + set_transformer(op_Store, gen_Store); + set_transformer(op_Const, gen_Const); + set_transformer(op_Load, gen_Load); + set_transformer(op_Sub, gen_Sub); + + set_transformer(op_be_AddSP, gen_be_AddSP); + set_transformer(op_be_SubSP, gen_be_SubSP); + set_transformer(op_be_Copy, gen_be_Copy); + set_transformer(op_be_Call, gen_be_Call); + set_transformer(op_be_FrameAddr, gen_be_FrameAddr); + + set_transformer(op_Cond, gen_Cond); + set_transformer(op_Cmp, gen_Cmp); + + set_transformer(op_SymConst, gen_SymConst); + + set_transformer(op_Phi, gen_Phi); + set_transformer(op_Proj, gen_Proj); + + set_transformer(op_Conv, gen_Conv); + 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_Eor, gen_Xor); + + set_transformer(op_Unknown, gen_Unknown); /* node list */ /* - be_set_transform_function(op_CopyB, gen_CopyB); - be_set_transform_function(op_Eor, gen_Eor); - be_set_transform_function(op_Quot, gen_Quot); - be_set_transform_function(op_Rotl, gen_Rotl); + set_transformer(op_CopyB, gen_CopyB); + set_transformer(op_Quot, gen_Quot); + set_transformer(op_Rotl, gen_Rotl); */ + + set_transformer(op_ASM, bad_transform); + set_transformer(op_Builtin, bad_transform); + set_transformer(op_CallBegin, bad_transform); + set_transformer(op_Cast, bad_transform); + set_transformer(op_Confirm, bad_transform); + set_transformer(op_DivMod, bad_transform); + set_transformer(op_EndExcept, bad_transform); + set_transformer(op_EndReg, bad_transform); + set_transformer(op_Filter, bad_transform); + set_transformer(op_Free, bad_transform); + set_transformer(op_Id, bad_transform); + set_transformer(op_InstOf, bad_transform); + + set_transformer(op_Mux, bad_transform); + set_transformer(op_Raise, bad_transform); + set_transformer(op_Sel, bad_transform); + set_transformer(op_Tuple, bad_transform); +} + + +/** + * Pre-transform all unknown nodes. + */ +static void sparc_pretransform_node(void) +{ + sparc_code_gen_t *cg = env_cg; + (void) cg; + //cg->unknown_gp = be_pre_transform_node(cg->unknown_gp); + //cg->unknown_fpa = be_pre_transform_node(cg->unknown_fpa); } /** @@ -1105,7 +1231,7 @@ void sparc_transform_graph(sparc_code_gen_t *cg) { sparc_register_transformers(); env_cg = cg; - be_transform_graph(cg->irg, NULL); + be_transform_graph(cg->irg, sparc_pretransform_node); } void sparc_init_transform(void)