- SPEC gzip laeuft
authorHannes Rapp <rapp@ipd.info.uni-karlsruhe.de>
Tue, 13 Jul 2010 11:37:08 +0000 (11:37 +0000)
committerHannes Rapp <rapp@ipd.info.uni-karlsruhe.de>
Tue, 13 Jul 2010 11:37:08 +0000 (11:37 +0000)
- Code soweit bereinigt

[r27734]

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 e5883b1..338c1da 100644 (file)
@@ -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 */
index 0e36800..44971cf 100644 (file)
@@ -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);
 
index 7713955..386dd16 100644 (file)
@@ -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");
index 6661575..d06b2e1 100644 (file)
@@ -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.
  */
index fe266ab..0ebac3c 100644 (file)
@@ -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
index 650377b..78b9fb3 100644 (file)
@@ -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",
index c602ad8..2ca1b0a 100644 (file)
@@ -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)