From: Matthias Braun Date: Tue, 27 Jul 2010 17:57:57 +0000 (+0000) Subject: first implementation of floatingpoint arithmetic operations X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=f89fe6bdc4d0f139557986320adfa37ea02d32b3;p=libfirm first implementation of floatingpoint arithmetic operations [r27825] --- diff --git a/ir/be/sparc/sparc_emitter.c b/ir/be/sparc/sparc_emitter.c index 2a921a4d6..898605dd0 100644 --- a/ir/be/sparc/sparc_emitter.c +++ b/ir/be/sparc/sparc_emitter.c @@ -222,44 +222,32 @@ void sparc_emit_mode_sign_prefix(const ir_node *node) be_emit_string(is_signed ? "s" : "u"); } -/** - * emit FP load mode char - */ -void sparc_emit_fp_load_mode(const ir_node *node) +static void emit_fp_suffix(const ir_mode *mode) { - 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); - + unsigned bits = get_mode_size_bits(mode); assert(mode_is_float(mode)); if (bits == 32) { - be_emit_string("f"); + be_emit_char('s'); } else if (bits == 64) { - be_emit_string("df"); + be_emit_char('d'); + } else if (bits == 128) { + be_emit_char('q'); } else { - panic("FP load mode > 64bits not implemented yet"); + panic("invalid FP mode"); } } -/** - * emit FP store mode char - */ -void sparc_emit_fp_store_mode(const ir_node *node) +void sparc_emit_fp_conv_source(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)); + const sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr_const(node); + emit_fp_suffix(attr->src_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"); - } +void sparc_emit_fp_conv_destination(const ir_node *node) +{ + const sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr_const(node); + emit_fp_suffix(attr->dest_mode); } /** @@ -267,18 +255,8 @@ void sparc_emit_fp_store_mode(const ir_node *node) */ 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"); - } + const sparc_fp_attr_t *attr = get_sparc_fp_attr_const(node); + emit_fp_suffix(attr->fp_mode); } /** @@ -361,40 +339,6 @@ 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 */ @@ -781,12 +725,10 @@ static void sparc_register_emitters(void) set_emitter(op_be_Return, emit_be_Return); set_emitter(op_sparc_BXX, emit_sparc_BXX); set_emitter(op_sparc_Call, emit_sparc_Call); - set_emitter(op_sparc_Div, emit_sparc_Div); set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr); set_emitter(op_sparc_HiImm, emit_sparc_HiImm); set_emitter(op_sparc_Ba, emit_sparc_Ba); set_emitter(op_sparc_LoImm, emit_sparc_LoImm); - set_emitter(op_sparc_Mul, emit_sparc_Mul); set_emitter(op_sparc_Mulh, emit_sparc_Mulh); set_emitter(op_sparc_Save, emit_sparc_Save); set_emitter(op_sparc_SymConst, emit_sparc_SymConst); diff --git a/ir/be/sparc/sparc_emitter.h b/ir/be/sparc/sparc_emitter.h index 9115065dc..ece24c268 100644 --- a/ir/be/sparc/sparc_emitter.h +++ b/ir/be/sparc/sparc_emitter.h @@ -44,8 +44,8 @@ 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_emit_fp_conv_source(const ir_node *node); +void sparc_emit_fp_conv_destination(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 d7b6d2942..354bf7596 100644 --- a/ir/be/sparc/sparc_new_nodes.c +++ b/ir/be/sparc/sparc_new_nodes.c @@ -71,6 +71,19 @@ static bool has_save_attr(const ir_node *node) return is_sparc_Save(node); } +static bool has_fp_attr(const ir_node *node) +{ + return is_sparc_fadd(node) || is_sparc_fsub(node) + || is_sparc_fmul(node) || is_sparc_fdiv(node) + || is_sparc_fftoi(node) || is_sparc_fitof(node) + || is_sparc_fneg(node); +} + +static bool has_fp_conv_attr(const ir_node *node) +{ + return is_sparc_fftof(node); +} + /** * Dumper interface for dumping sparc nodes in vcg. * @param F the output file @@ -120,6 +133,15 @@ static void sparc_dump_node(FILE *F, ir_node *n, dump_reason_t reason) fprintf(F, "n projs: %d\n", attr->n_projs); fprintf(F, "default proj: %ld\n", attr->default_proj_num); } + if (has_fp_attr(n)) { + const sparc_fp_attr_t *attr = get_sparc_fp_attr_const(n); + ir_fprintf(F, "fp_mode: %+F\n", attr->fp_mode); + } + if (has_fp_conv_attr(n)) { + const sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr_const(n); + ir_fprintf(F, "conv from: %+F\n", attr->src_mode); + ir_fprintf(F, "conv to: %+F\n", attr->dest_mode); + } break; case dump_node_nodeattr_txt: @@ -239,6 +261,30 @@ const sparc_save_attr_t *get_sparc_save_attr_const(const ir_node *node) return (const sparc_save_attr_t*) get_irn_generic_attr_const(node); } +sparc_fp_attr_t *get_sparc_fp_attr(ir_node *node) +{ + assert(has_fp_attr(node)); + return (sparc_fp_attr_t*) get_irn_generic_attr(node); +} + +const sparc_fp_attr_t *get_sparc_fp_attr_const(const ir_node *node) +{ + assert(has_fp_attr(node)); + return (const sparc_fp_attr_t*) get_irn_generic_attr_const(node); +} + +sparc_fp_conv_attr_t *get_sparc_fp_conv_attr(ir_node *node) +{ + assert(has_fp_conv_attr(node)); + return (sparc_fp_conv_attr_t*) get_irn_generic_attr(node); +} + +const sparc_fp_conv_attr_t *get_sparc_fp_conv_attr_const(const ir_node *node) +{ + assert(has_fp_conv_attr(node)); + return (const sparc_fp_conv_attr_t*) get_irn_generic_attr_const(node); +} + /** * Returns the argument register requirements of a sparc node. */ @@ -295,7 +341,6 @@ static void init_sparc_attributes(ir_node *node, arch_irn_flags_t flags, memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0])); } -/* CUSTOM ATTRIBUTE INIT FUNCTIONS */ static void init_sparc_load_store_attributes(ir_node *res, ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, @@ -317,12 +362,26 @@ static void init_sparc_symconst_attributes(ir_node *res, ir_entity *entity) attr->fp_offset = 0; } -static void init_sparc_save_attr(ir_node *res, int initial_stacksize) +static void init_sparc_save_attributes(ir_node *res, int initial_stacksize) { sparc_save_attr_t *attr = get_sparc_save_attr(res); attr->initial_stacksize = initial_stacksize; } +static void init_sparc_fp_attributes(ir_node *res, ir_mode *fp_mode) +{ + sparc_fp_attr_t *attr = get_sparc_fp_attr(res); + attr->fp_mode = fp_mode; +} + +static void init_sparc_fp_conv_attributes(ir_node *res, ir_mode *src_mode, + ir_mode *dest_mode) +{ + sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr(res); + attr->src_mode = src_mode; + attr->dest_mode = dest_mode; +} + /** * copies sparc attributes of node */ @@ -354,15 +413,13 @@ static int cmp_attr_sparc(ir_node *a, ir_node *b) || attr_a->is_load_store != attr_b->is_load_store; } - -/* CUSTOM ATTRIBUTE CMP FUNCTIONS */ static int cmp_attr_sparc_load_store(ir_node *a, ir_node *b) { const sparc_load_store_attr_t *attr_a = get_sparc_load_store_attr_const(a); const sparc_load_store_attr_t *attr_b = get_sparc_load_store_attr_const(b); if (cmp_attr_sparc(a, b)) - return 1; + return 1; return attr_a->entity != attr_b->entity || attr_a->entity_sign != attr_b->entity_sign @@ -377,7 +434,7 @@ static int cmp_attr_sparc_symconst(ir_node *a, ir_node *b) const sparc_symconst_attr_t *attr_b = get_sparc_symconst_attr_const(b); if (cmp_attr_sparc(a, b)) - return 1; + return 1; return attr_a->entity != attr_b->entity || attr_a->fp_offset != attr_b->fp_offset; @@ -389,7 +446,7 @@ static int cmp_attr_sparc_jmp_cond(ir_node *a, ir_node *b) const sparc_jmp_cond_attr_t *attr_b = get_sparc_jmp_cond_attr_const(b); if (cmp_attr_sparc(a, b)) - return 1; + return 1; return attr_a->proj_num != attr_b->proj_num || attr_a->is_unsigned != attr_b->is_unsigned; @@ -401,7 +458,7 @@ static int cmp_attr_sparc_jmp_switch(ir_node *a, ir_node *b) const sparc_jmp_switch_attr_t *attr_b = get_sparc_jmp_switch_attr_const(b); if (cmp_attr_sparc(a, b)) - return 1; + return 1; return attr_a->default_proj_num != attr_b->default_proj_num || attr_a->n_projs != attr_b->n_projs; @@ -413,10 +470,33 @@ static int cmp_attr_sparc_save(ir_node *a, ir_node *b) const sparc_save_attr_t *attr_b = get_sparc_save_attr_const(b); if (cmp_attr_sparc(a, b)) - return 1; + return 1; return attr_a->initial_stacksize != attr_b->initial_stacksize; } +static int cmp_attr_sparc_fp(ir_node *a, ir_node *b) +{ + const sparc_fp_attr_t *attr_a = get_sparc_fp_attr_const(a); + const sparc_fp_attr_t *attr_b = get_sparc_fp_attr_const(b); + + if (cmp_attr_sparc(a, b)) + return 1; + + return attr_a->fp_mode != attr_b->fp_mode; +} + +static int cmp_attr_sparc_fp_conv(ir_node *a, ir_node *b) +{ + const sparc_fp_conv_attr_t *attr_a = get_sparc_fp_conv_attr_const(a); + const sparc_fp_conv_attr_t *attr_b = get_sparc_fp_conv_attr_const(b); + + if (cmp_attr_sparc(a, b)) + return 1; + + return attr_a->src_mode != attr_b->src_mode + || attr_a->dest_mode != attr_b->dest_mode;; +} + /* Include the generated constructor functions */ #include "gen_sparc_new_nodes.c.inl" diff --git a/ir/be/sparc/sparc_new_nodes.h b/ir/be/sparc/sparc_new_nodes.h index 93d073c85..89af0eebf 100644 --- a/ir/be/sparc/sparc_new_nodes.h +++ b/ir/be/sparc/sparc_new_nodes.h @@ -48,6 +48,12 @@ const sparc_jmp_switch_attr_t *get_sparc_jmp_switch_attr_const(const ir_node *no 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); +sparc_fp_attr_t *get_sparc_fp_attr(ir_node *node); +const sparc_fp_attr_t *get_sparc_fp_attr_const(const ir_node *node); + +sparc_fp_conv_attr_t *get_sparc_fp_conv_attr(ir_node *node); +const sparc_fp_conv_attr_t *get_sparc_fp_conv_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 c48f313ef..b7f4aa45d 100644 --- a/ir/be/sparc/sparc_nodes_attr.h +++ b/ir/be/sparc/sparc_nodes_attr.h @@ -47,8 +47,15 @@ struct sparc_attr_t */ 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 */ + sparc_attr_t base; /**< generic attribute */ + ir_mode *fp_mode; +}; + +typedef struct sparc_fp_conv_attr_t sparc_fp_conv_attr_t; +struct sparc_fp_conv_attr_t { + sparc_attr_t base; + ir_mode *src_mode; + ir_mode *dest_mode; }; /** diff --git a/ir/be/sparc/sparc_spec.pl b/ir/be/sparc/sparc_spec.pl index 1f3713c91..4e2da4d9b 100644 --- a/ir/be/sparc/sparc_spec.pl +++ b/ir/be/sparc/sparc_spec.pl @@ -121,11 +121,10 @@ $state = 32; # register represents a state IM => "${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);", + FCONVS => "${arch}_emit_fp_conv_source(node);", + FCONVD => "${arch}_emit_fp_conv_destination(node);", + O => "${arch}_emit_offset(node);", ); $default_attr_type = "sparc_attr_t"; @@ -141,7 +140,10 @@ $default_copy_attr = "sparc_copy_attr"; sparc_jmp_cond_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);", sparc_jmp_switch_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);", sparc_save_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);", - + sparc_fp_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n". + "\tinit_sparc_fp_attributes(res, fp_mode);\n", + sparc_fp_conv_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);". + "\tinit_sparc_fp_conv_attributes(res, src_mode, dest_mode);\n", ); %compare_attr = ( @@ -151,6 +153,8 @@ $default_copy_attr = "sparc_copy_attr"; sparc_jmp_cond_attr_t => "cmp_attr_sparc_jmp_cond", sparc_jmp_switch_attr_t => "cmp_attr_sparc_jmp_switch", sparc_save_attr_t => "cmp_attr_sparc_save", + sparc_fp_attr_t => "cmp_attr_sparc_fp", + sparc_fp_conv_attr_t => "cmp_attr_sparc_fp_conv", ); # addressing modes: imm, reg, reg +/- imm, reg + reg @@ -273,7 +277,7 @@ Save => { outs => [ "stack", "frame", "mem" ], attr => "int initial_stacksize", attr_type => "sparc_save_attr_t", - init_attr => "\tinit_sparc_save_attr(res, initial_stacksize);", + init_attr => "\tinit_sparc_save_attributes(res, initial_stacksize);", }, SubSP => { @@ -374,7 +378,7 @@ SwitchJmp => { Sll => { irn_flags => [ "rematerializable" ], - mode => $mode_gp, + mode => $mode_gp, reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, emit => '. sll %S1, %R2I, %D1', constructors => \%binop_operand_constructors, @@ -382,7 +386,7 @@ Sll => { Slr => { irn_flags => [ "rematerializable" ], - mode => $mode_gp, + mode => $mode_gp, reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, emit => '. srl %S1, %R2I, %D1', constructors => \%binop_operand_constructors, @@ -390,7 +394,7 @@ Slr => { Sra => { irn_flags => [ "rematerializable" ], - mode => $mode_gp, + mode => $mode_gp, reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, emit => '. sra %S1, %R2I, %D1', constructors => \%binop_operand_constructors, @@ -398,7 +402,7 @@ Sra => { And => { irn_flags => [ "rematerializable" ], - mode => $mode_gp, + mode => $mode_gp, reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, emit => '. and %S1, %R2I, %D1', constructors => \%binop_operand_constructors, @@ -406,7 +410,7 @@ And => { Or => { irn_flags => [ "rematerializable" ], - mode => $mode_gp, + mode => $mode_gp, reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, emit => '. or %S1, %R2I, %D1', constructors => \%binop_operand_constructors, @@ -414,22 +418,20 @@ Or => { Xor => { irn_flags => [ "rematerializable" ], - mode => $mode_gp, + mode => $mode_gp, reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, emit => '. xor %S1, %R2I, %D1', constructors => \%binop_operand_constructors, }, Mul => { - state => "exc_pinned", - reg_req => { in => [ "gp", "gp" ], out => [ "gp", "flags" ] }, - outs => [ "low", "high" ], + reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, constructors => \%binop_operand_constructors, - #emit =>'. mul %S1, %R2I, %D1' + emit => '. mul %S1, %R2I, %D1', + mode => $mode_gp, }, Mulh => { - state => "exc_pinned", reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] }, outs => [ "low", "high" ], constructors => \%binop_operand_constructors, @@ -438,25 +440,24 @@ Mulh => { Div => { irn_flags => [ "rematerializable" ], state => "exc_pinned", - reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - outs => [ "res" ], + reg_req => { in => [ "gp", "gp" ], out => [ "gp", "none" ] }, + outs => [ "res", "M" ], constructors => \%binop_operand_constructors, - #mode => $mode_gp, - #emit =>'. div %S1, %R2I, %D1' + emit => '. div %S1, %R2I, %D1', }, Minus => { irn_flags => [ "rematerializable" ], - mode => $mode_gp, + mode => $mode_gp, reg_req => { in => [ "gp" ], out => [ "gp" ] }, emit => ". sub %%g0, %S1, %D1" }, Not => { - irn_flags => [ "rematerializable" ], - mode => $mode_gp, - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. xnor %S1, %%g0, %D1' + irn_flags => [ "rematerializable" ], + mode => $mode_gp, + reg_req => { in => [ "gp" ], out => [ "gp" ] }, + emit => '. xnor %S1, %%g0, %D1' }, Nop => { @@ -465,59 +466,87 @@ Nop => { emit => '. nop', }, -fAdd => { +fadd => { op_flags => [ "commutative" ], irn_flags => [ "rematerializable" ], reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, - emit => '. fadd%FPM %S1, %S2, %D1' + emit => '. fadd%FPM %S1, %S2, %D1', + attr_type => "sparc_fp_attr_t", + attr => "ir_mode *fp_mode", + mode => $mode_fp, }, -fMul => { - op_flags => [ "commutative" ], +fsub => { + irn_flags => [ "rematerializable" ], reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, - emit =>'. fmul%FPM %S1, %S2, %D1' + emit => '. fsub%FPM %S1, %S2, %D1', + attr_type => "sparc_fp_attr_t", + attr => "ir_mode *fp_mode", + mode => $mode_fp, }, -fsMuld => { +fmul => { + irn_flags => [ "rematerializable" ], op_flags => [ "commutative" ], reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, - emit =>'. fsmuld %S1, %S2, %D1' + emit =>'. fmul%FPM %S1, %S2, %D1', + attr_type => "sparc_fp_attr_t", + attr => "ir_mode *fp_mode", + mode => $mode_fp, }, -FsTOd => { +fdiv => { irn_flags => [ "rematerializable" ], - reg_req => { in => [ "fp" ], out => [ "fp" ] }, - emit =>'. FsTOd %S1, %D1' + reg_req => { in => [ "fp", "fp" ], out => [ "fp", "none" ] }, + emit => '. fdiv%FPM %S1, %S2, %D1', + attr_type => "sparc_fp_attr_t", + attr => "ir_mode *fp_mode", + outs => [ "res", "M" ], }, -FdTOs => { +fneg => { irn_flags => [ "rematerializable" ], reg_req => { in => [ "fp" ], out => [ "fp" ] }, - emit =>'. FdTOs %S1, %D1' + emit => '. fneg%FPM %S1, %D1', + attr_type => "sparc_fp_attr_t", + attr => "ir_mode *fp_mode", + mode => $mode_fp, }, -FiTOs => { +"fabs" => { irn_flags => [ "rematerializable" ], - reg_req => { in => [ "gp" ], out => [ "fp" ] }, - emit =>'. FiTOs %S1, %D1' + reg_req => { in => [ "fp" ], out => [ "fp" ] }, + emit => '. fabs%FPM %S1, %D1', + attr_type => "sparc_fp_attr_t", + attr => "ir_mode *fp_mode", + mode => $mode_fp, }, -FiTOd => { +fftof => { irn_flags => [ "rematerializable" ], - reg_req => { in => [ "gp" ], out => [ "fp" ] }, - emit =>'. FiTOd %S1, %D1' + reg_req => { in => [ "fp" ], out => [ "fp" ] }, + emit => '. f%FCONVS.to%FCONVD %S1, %D1', + attr_type => "sparc_fp_conv_attr_t", + attr => "ir_mode *src_mode, ir_mode *dest_mode", + mode => $mode_fp, }, -FsTOi => { +fitof => { irn_flags => [ "rematerializable" ], - reg_req => { in => [ "fp" ], out => [ "gp" ] }, - emit =>'. FsTOi %S1, %D1' + reg_req => { in => [ "gp" ], out => [ "fp" ] }, + emit => '. fito%FPM %S1, %D1', + attr_type => "sparc_fp_attr_t", + attr => "ir_mode *fp_mode", + mode => $mode_fp, }, -FdTOi => { +fftoi => { irn_flags => [ "rematerializable" ], reg_req => { in => [ "fp" ], out => [ "gp" ] }, - emit =>'. FdTOi %S1, %D1' + emit => '. f%FPM.toi %S1, %D1', + attr_type => "sparc_fp_attr_t", + attr => "ir_mode *fp_mode", + mode => $mode_gp, }, Ldf => { diff --git a/ir/be/sparc/sparc_transform.c b/ir/be/sparc/sparc_transform.c index b12d062cd..2cbf4845d 100644 --- a/ir/be/sparc/sparc_transform.c +++ b/ir/be/sparc/sparc_transform.c @@ -148,7 +148,6 @@ static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op, } } - /** * Creates a possible DAG for a constant. */ @@ -170,7 +169,6 @@ static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block, return result; } - /** * Create a DAG constructing a given Const. * @@ -257,18 +255,17 @@ static ir_node *gen_helper_binop(ir_node *node, match_flags_t flags, /** * helper function for FP binop operations */ -static ir_node *gen_helper_binfpop(ir_node *node, new_binop_fp_func new_reg) +static ir_node *gen_helper_binfpop(ir_node *node, ir_mode *mode, + new_binop_fp_func new_func) { ir_node *block = be_transform_node(get_nodes_block(node)); ir_node *op1 = get_binop_left(node); - ir_node *new_op1; + ir_node *new_op1 = be_transform_node(op1); ir_node *op2 = get_binop_right(node); - ir_node *new_op2; + ir_node *new_op2 = be_transform_node(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)); + return new_func(dbgi, block, new_op1, new_op2, mode); } /** @@ -281,13 +278,13 @@ static ir_node *gen_Add(ir_node *node) { ir_mode *mode = get_irn_mode(node); - if (mode_is_float(mode)) - panic("FP not implemented yet"); + if (mode_is_float(mode)) { + return gen_helper_binfpop(node, mode, new_bd_sparc_fadd); + } return gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_Add_reg, new_bd_sparc_Add_imm); } - /** * Creates an sparc Sub. * @@ -297,13 +294,14 @@ static ir_node *gen_Add(ir_node *node) static ir_node *gen_Sub(ir_node *node) { ir_mode *mode = get_irn_mode(node); - if (mode_is_float(mode)) - panic("FP not implemented yet"); + + if (mode_is_float(mode)) { + return gen_helper_binfpop(node, mode, new_bd_sparc_fsub); + } return gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_Sub_reg, new_bd_sparc_Sub_imm); } - /** * Transforms a Load. * @@ -321,17 +319,16 @@ static ir_node *gen_Load(ir_node *node) dbg_info *dbgi = get_irn_dbg_info(node); ir_node *new_load = NULL; - if (mode_is_float(mode)) - panic("SPARC: no fp implementation yet"); - - new_load = new_bd_sparc_Ld(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false); + if (mode_is_float(mode)) { + new_load = new_bd_sparc_Ldf(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false); + } else { + new_load = new_bd_sparc_Ld(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false); + } set_irn_pinned(new_load, get_irn_pinned(node)); return new_load; } - - /** * Transforms a Store. * @@ -351,10 +348,12 @@ static ir_node *gen_Store(ir_node *node) dbg_info *dbgi = get_irn_dbg_info(node); ir_node *new_store = NULL; - if (mode_is_float(mode)) - panic("SPARC: no fp implementation yet"); - - new_store = new_bd_sparc_St(dbgi, block, new_ptr, new_val, new_mem, mode, NULL, 0, 0, false); + if (mode_is_float(mode)) { + new_store = new_bd_sparc_Stf(dbgi, block, new_ptr, new_val, new_mem, mode, NULL, 0, 0, false); + } else { + new_store = new_bd_sparc_St(dbgi, block, new_ptr, new_val, new_mem, mode, NULL, 0, 0, false); + } + set_irn_pinned(new_store, get_irn_pinned(node)); return new_store; } @@ -365,22 +364,16 @@ static ir_node *gen_Store(ir_node *node) * * @return the created sparc Mul node */ -static ir_node *gen_Mul(ir_node *node) { - ir_mode *mode = get_irn_mode(node); - ir_node *mul; - ir_node *proj_res_low; - +static ir_node *gen_Mul(ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); if (mode_is_float(mode)) { - mul = gen_helper_binfpop(node, new_bd_sparc_fMul); - return mul; + return gen_helper_binfpop(node, mode, new_bd_sparc_fmul); } assert(mode_is_data(mode)); - 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_r_Proj(mul, mode_gp, pn_sparc_Mul_low); - return proj_res_low; + return gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, + new_bd_sparc_Mul_reg, new_bd_sparc_Mul_imm); } /** @@ -389,7 +382,8 @@ static ir_node *gen_Mul(ir_node *node) { * * @return the created sparc Mulh node */ -static ir_node *gen_Mulh(ir_node *node) { +static ir_node *gen_Mulh(ir_node *node) +{ ir_mode *mode = get_irn_mode(node); ir_node *mul; ir_node *proj_res_hi; @@ -410,20 +404,19 @@ static ir_node *gen_Mulh(ir_node *node) { * * @return the created sparc Div node */ -static ir_node *gen_Div(ir_node *node) { - - ir_mode *mode = get_irn_mode(node); - - ir_node *div; - - if (mode_is_float(mode)) - panic("FP not supported yet"); - - //assert(mode_is_data(mode)); - div = gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_Div_reg, new_bd_sparc_Div_imm); - return div; +static ir_node *gen_Div(ir_node *node) +{ + ir_mode *mode = get_Div_resmode(node); + assert(!mode_is_float(mode)); + return gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_Div_reg, new_bd_sparc_Div_imm); } +static ir_node *gen_Quot(ir_node *node) +{ + ir_mode *mode = get_Quot_resmode(node); + assert(mode_is_float(mode)); + return gen_helper_binfpop(node, mode, new_bd_sparc_fdiv); +} /** * transform abs node: @@ -500,25 +493,21 @@ static ir_node *gen_Shrs(ir_node *node) return gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_Sra_reg, new_bd_sparc_Sra_imm); } -/****** TRANSFORM GENERAL BACKEND NODES ********/ - /** * Transforms a Minus node. - * */ static ir_node *gen_Minus(ir_node *node) { - ir_node *block = be_transform_node(get_nodes_block(node)); - ir_node *op = get_Minus_op(node); - ir_node *new_op = be_transform_node(op); - dbg_info *dbgi = get_irn_dbg_info(node); - ir_mode *mode = get_irn_mode(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op = get_Minus_op(node); + ir_node *new_op = be_transform_node(op); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_mode *mode = get_irn_mode(node); if (mode_is_float(mode)) { - panic("FP not implemented yet"); + return new_bd_sparc_fneg(dbgi, block, new_op, mode); } - assert(mode_is_data(mode)); return new_bd_sparc_Minus(dbgi, block, new_op); } @@ -607,7 +596,6 @@ static ir_node *gen_be_AddSP(ir_node *node) return new_op; } - /** * SubSP * @param node the ir SubSP node @@ -844,32 +832,18 @@ static ir_node *gen_Conv(ir_node *node) if (mode_is_float(src_mode)) { if (mode_is_float(dst_mode)) { /* float -> float conv */ - if (src_bits > dst_bits) { - return new_bd_sparc_FsTOd(dbg, block, new_op, dst_mode); - } else { - return new_bd_sparc_FdTOs(dbg, block, new_op, dst_mode); - } + return new_bd_sparc_fftof(dbg, block, new_op, src_mode, dst_mode); } else { /* float -> int conv */ - switch (dst_bits) { - case 32: - return new_bd_sparc_FsTOi(dbg, block, new_op, dst_mode); - case 64: - return new_bd_sparc_FdTOi(dbg, block, new_op, dst_mode); - default: - panic("quad FP not implemented"); - } + if (!mode_is_signed(dst_mode)) + panic("float to unsigned not implemented yet"); + return new_bd_sparc_fftoi(dbg, block, new_op, src_mode); } } else { /* int -> float conv */ - switch (dst_bits) { - case 32: - return new_bd_sparc_FiTOs(dbg, block, new_op, src_mode); - case 64: - return new_bd_sparc_FiTOd(dbg, block, new_op, src_mode); - default: - panic("quad FP not implemented"); - } + if (!mode_is_signed(src_mode)) + panic("unsigned to float not implemented yet"); + return new_bd_sparc_fitof(dbg, block, new_op, dst_mode); } } else { /* complete in gp registers */ int min_bits; @@ -1352,7 +1326,6 @@ static ir_node *gen_Phi(ir_node *node) return phi; } - /** * Transform a Proj from a Load. */ @@ -1361,23 +1334,53 @@ static ir_node *gen_Proj_Load(ir_node *node) ir_node *load = get_Proj_pred(node); ir_node *new_load = be_transform_node(load); dbg_info *dbgi = get_irn_dbg_info(node); - long proj = get_Proj_proj(node); + long pn = get_Proj_proj(node); /* renumber the proj */ switch (get_sparc_irn_opcode(new_load)) { - case iro_sparc_Ld: - /* handle all gp loads equal: they have the same proj numbers. */ - if (proj == pn_Load_res) { - return new_rd_Proj(dbgi, new_load, mode_gp, pn_sparc_Ld_res); - } else if (proj == pn_Load_M) { - return new_rd_Proj(dbgi, new_load, mode_M, pn_sparc_Ld_M); - } - break; - default: - panic("Unsupported Proj from Load"); + case iro_sparc_Ld: + /* handle all gp loads equal: they have the same proj numbers. */ + if (pn == pn_Load_res) { + return new_rd_Proj(dbgi, new_load, mode_gp, pn_sparc_Ld_res); + } else if (pn == pn_Load_M) { + return new_rd_Proj(dbgi, new_load, mode_M, pn_sparc_Ld_M); + } + break; + case iro_sparc_Ldf: + if (pn == pn_Load_res) { + return new_rd_Proj(dbgi, new_load, mode_fp, pn_sparc_Ldf_res); + } else if (pn == pn_Load_M) { + return new_rd_Proj(dbgi, new_load, mode_M, pn_sparc_Ld_M); + } + break; + default: + break; } + panic("Unsupported Proj from Load"); +} - return be_duplicate_node(node); +static ir_node *gen_Proj_Store(ir_node *node) +{ + ir_node *store = get_Proj_pred(node); + ir_node *new_store = be_transform_node(store); + long pn = get_Proj_proj(node); + + /* renumber the proj */ + switch (get_sparc_irn_opcode(new_store)) { + case iro_sparc_St: + if (pn == pn_Store_M) { + return new_store; + } + break; + case iro_sparc_Stf: + if (pn == pn_Store_M) { + return new_store; + } + break; + default: + break; + } + panic("Unsupported Proj from Store"); } /** @@ -1396,20 +1399,38 @@ static ir_node *gen_Proj_Div(ir_node *node) { ir_node *pred = get_Proj_pred(node); ir_node *new_pred = be_transform_node(pred); - long proj = get_Proj_proj(node); + long pn = get_Proj_proj(node); - switch (proj) { + assert(is_sparc_Div(new_pred)); + switch (pn) { case pn_Div_res: - if (is_sparc_Div(new_pred)) { - return new_r_Proj(new_pred, mode_gp, pn_sparc_Div_res); - } - break; + return new_r_Proj(new_pred, mode_gp, pn_sparc_Div_res); + case pn_Div_M: + return new_r_Proj(new_pred, mode_gp, pn_sparc_Div_M); default: break; } panic("Unsupported Proj from Div"); } +static ir_node *gen_Proj_Quot(ir_node *node) +{ + ir_node *pred = get_Proj_pred(node); + ir_node *new_pred = be_transform_node(pred); + long pn = get_Proj_proj(node); + + assert(is_sparc_fdiv(new_pred)); + switch (pn) { + case pn_Quot_res: + return new_r_Proj(new_pred, mode_gp, pn_sparc_fdiv_res); + case pn_Quot_M: + return new_r_Proj(new_pred, mode_gp, pn_sparc_fdiv_M); + default: + break; + } + panic("Unsupported Proj from Quot"); +} + static ir_node *gen_Proj_Start(ir_node *node) { ir_node *block = get_nodes_block(node); @@ -1551,16 +1572,10 @@ static ir_node *gen_Proj_Proj_Call(ir_node *node) static ir_node *gen_Proj(ir_node *node) { ir_node *pred = get_Proj_pred(node); - long pn = get_Proj_proj(node); switch (get_irn_opcode(pred)) { case iro_Store: - if (pn == pn_Store_M) { - return be_transform_node(pred); - } else { - panic("Unsupported Proj from Store"); - } - break; + return gen_Proj_Store(node); case iro_Load: return gen_Proj_Load(node); case iro_Call: @@ -1571,6 +1586,8 @@ static ir_node *gen_Proj(ir_node *node) return be_duplicate_node(node); case iro_Div: return gen_Proj_Div(node); + case iro_Quot: + return gen_Proj_Quot(node); case iro_Start: return gen_Proj_Start(node); case iro_Proj: { @@ -1587,7 +1604,6 @@ static ir_node *gen_Proj(ir_node *node) } } - /** * transform a Jmp */ @@ -1631,6 +1647,7 @@ void sparc_register_transformers(void) be_set_transform_function(op_Or, gen_Or); be_set_transform_function(op_Phi, gen_Phi); be_set_transform_function(op_Proj, gen_Proj); + be_set_transform_function(op_Quot, gen_Quot); be_set_transform_function(op_Return, gen_Return); be_set_transform_function(op_Sel, gen_Sel); be_set_transform_function(op_Shl, gen_Shl);