first implementation of floatingpoint arithmetic operations
authorMatthias Braun <matze@braunis.de>
Tue, 27 Jul 2010 17:57:57 +0000 (17:57 +0000)
committerMatthias Braun <matze@braunis.de>
Tue, 27 Jul 2010 17:57:57 +0000 (17:57 +0000)
[r27825]

ir/be/sparc/sparc_emitter.c
ir/be/sparc/sparc_emitter.h
ir/be/sparc/sparc_new_nodes.c
ir/be/sparc/sparc_new_nodes.h
ir/be/sparc/sparc_nodes_attr.h
ir/be/sparc/sparc_spec.pl
ir/be/sparc/sparc_transform.c

index 2a921a4..898605d 100644 (file)
@@ -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);
index 9115065..ece24c2 100644 (file)
@@ -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);
 
index d7b6d29..354bf75 100644 (file)
@@ -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"
index 93d073c..89af0ee 100644 (file)
@@ -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.
  */
index c48f313..b7f4aa4 100644 (file)
@@ -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;
 };
 
 /**
index 1f3713c..4e2da4d 100644 (file)
@@ -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 => {
index b12d062..2cbf484 100644 (file)
@@ -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);