sparc: implement/fix remaining float<->int conversions
[libfirm] / ir / be / sparc / sparc_transform.c
index 4027c18..db76d95 100644 (file)
@@ -89,7 +89,7 @@ static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
                return new_bd_sparc_And_imm(dbgi, block, op, NULL, 0xFF);
        } else if (src_bits == 16) {
                ir_node *lshift = new_bd_sparc_Sll_imm(dbgi, block, op, NULL, 16);
-               ir_node *rshift = new_bd_sparc_Slr_imm(dbgi, block, lshift, NULL, 16);
+               ir_node *rshift = new_bd_sparc_Srl_imm(dbgi, block, lshift, NULL, 16);
                return rshift;
        } else {
                panic("zero extension only supported for 8 and 16 bits");
@@ -726,7 +726,7 @@ static ir_node *gen_helper_bitop(ir_node *node,
        ir_node *op1 = get_binop_left(node);
        ir_node *op2 = get_binop_right(node);
        if (is_Not(op1)) {
-               return gen_helper_binop_args(node, get_Not_op(op1), op2,
+               return gen_helper_binop_args(node, op2, get_Not_op(op1),
                                             MATCH_MODE_NEUTRAL,
                                             new_not_reg, new_not_imm);
        }
@@ -774,7 +774,7 @@ static ir_node *gen_Shl(ir_node *node)
 
 static ir_node *gen_Shr(ir_node *node)
 {
-       return gen_helper_binop(node, MATCH_NONE, new_bd_sparc_Slr_reg, new_bd_sparc_Slr_imm);
+       return gen_helper_binop(node, MATCH_NONE, new_bd_sparc_Srl_reg, new_bd_sparc_Srl_imm);
 }
 
 static ir_node *gen_Shrs(ir_node *node)
@@ -902,34 +902,16 @@ static ir_node *gen_SwitchJmp(ir_node *node)
        ir_node         *block        = be_transform_node(get_nodes_block(node));
        ir_node         *selector     = get_Cond_selector(node);
        ir_node         *new_selector = be_transform_node(selector);
-       long             switch_min   = LONG_MAX;
-       long             switch_max   = LONG_MIN;
        long             default_pn   = get_Cond_default_proj(node);
        ir_entity       *entity;
        ir_node         *table_address;
        ir_node         *index;
        ir_node         *load;
        ir_node         *address;
-       unsigned         length;
-       const ir_edge_t *edge;
 
        /* switch with smaller mode not implemented yet */
        assert(get_mode_size_bits(get_irn_mode(selector)) == 32);
 
-       foreach_out_edge(node, edge) {
-               ir_node *proj = get_edge_src_irn(edge);
-               long     pn   = get_Proj_proj(proj);
-               if (pn == default_pn)
-                       continue;
-
-               switch_min = pn<switch_min ? pn : switch_min;
-               switch_max = pn>switch_max ? pn : switch_max;
-       }
-       length = (unsigned long) (switch_max - switch_min);
-       if (length > 16000) {
-               panic("Size of switch %+F bigger than 16000", node);
-       }
-
        entity = new_entity(NULL, id_unique("TBL%u"), get_unknown_type());
        set_entity_visibility(entity, ir_visibility_private);
        add_entity_linkage(entity, IR_LINKAGE_CONSTANT);
@@ -940,8 +922,7 @@ static ir_node *gen_SwitchJmp(ir_node *node)
         * done. */
 
        /* construct base address */
-       table_address = make_address(dbgi, block, entity,
-                                    -switch_min * get_mode_size_bytes(mode_gp));
+       table_address = make_address(dbgi, block, entity, 0);
        /* scale index */
        index = new_bd_sparc_Sll_imm(dbgi, block, new_selector, NULL, 2);
        /* load from jumptable */
@@ -1089,35 +1070,57 @@ static ir_node *create_fftof(dbg_info *dbgi, ir_node *block, ir_node *op,
 static ir_node *create_ftoi(dbg_info *dbgi, ir_node *block, ir_node *op,
                             ir_mode *src_mode)
 {
-       unsigned bits = get_mode_size_bits(src_mode);
+       ir_node  *ftoi;
+       unsigned  bits = get_mode_size_bits(src_mode);
        if (bits == 32) {
-               return new_bd_sparc_fftoi_s(dbgi, block, op, src_mode);
+               ftoi = new_bd_sparc_fftoi_s(dbgi, block, op, src_mode);
        } else if (bits == 64) {
-               return new_bd_sparc_fftoi_d(dbgi, block, op, src_mode);
+               ftoi = new_bd_sparc_fftoi_d(dbgi, block, op, src_mode);
        } else {
                assert(bits == 128);
-               return new_bd_sparc_fftoi_q(dbgi, block, op, src_mode);
+               ftoi = new_bd_sparc_fftoi_q(dbgi, block, op, src_mode);
+       }
+
+       {
+       ir_graph *irg   = get_irn_irg(block);
+       ir_node  *sp    = get_irg_frame(irg);
+       ir_node  *nomem = new_r_NoMem(irg);
+       ir_node  *stf   = create_stf(dbgi, block, ftoi, sp, nomem, src_mode,
+                                    NULL, 0, true);
+       ir_node  *ld    = new_bd_sparc_Ld_imm(dbgi, block, sp, stf, mode_gp,
+                                             NULL, 0, true);
+       ir_node  *res   = new_r_Proj(ld, mode_gp, pn_sparc_Ld_res);
+       set_irn_pinned(stf, op_pin_state_floats);
+       set_irn_pinned(ld, op_pin_state_floats);
+       return res;
        }
 }
 
 static ir_node *create_itof(dbg_info *dbgi, ir_node *block, ir_node *op,
                             ir_mode *dst_mode)
 {
-       unsigned bits = get_mode_size_bits(dst_mode);
+       ir_graph *irg   = get_irn_irg(block);
+       ir_node  *sp    = get_irg_frame(irg);
+       ir_node  *nomem = new_r_NoMem(irg);
+       ir_node  *st    = new_bd_sparc_St_imm(dbgi, block, op, sp, nomem,
+                                             mode_gp, NULL, 0, true);
+       ir_node  *ldf   = new_bd_sparc_Ldf_s(dbgi, block, sp, st, mode_fp,
+                                            NULL, 0, true);
+       ir_node  *res   = new_r_Proj(ldf, mode_fp, pn_sparc_Ldf_res);
+       unsigned  bits  = get_mode_size_bits(dst_mode);
+       set_irn_pinned(st, op_pin_state_floats);
+       set_irn_pinned(ldf, op_pin_state_floats);
+
        if (bits == 32) {
-               return new_bd_sparc_fitof_s(dbgi, block, op, dst_mode);
+               return new_bd_sparc_fitof_s(dbgi, block, res, dst_mode);
        } else if (bits == 64) {
-               return new_bd_sparc_fitof_d(dbgi, block, op, dst_mode);
+               return new_bd_sparc_fitof_d(dbgi, block, res, dst_mode);
        } else {
                assert(bits == 128);
-               return new_bd_sparc_fitof_q(dbgi, block, op, dst_mode);
+               return new_bd_sparc_fitof_q(dbgi, block, res, dst_mode);
        }
 }
 
-/**
- * Transforms a Conv node.
- *
- */
 static ir_node *gen_Conv(ir_node *node)
 {
        ir_node  *block    = be_transform_node(get_nodes_block(node));
@@ -1148,8 +1151,11 @@ static ir_node *gen_Conv(ir_node *node)
                        }
                } else {
                        /* int -> float conv */
-                       if (!mode_is_signed(src_mode))
-                               panic("unsigned to float not implemented yet");
+                       if (src_bits < 32) {
+                               new_op = gen_extension(dbg, block, new_op, src_mode);
+                       } else if (src_bits == 32 && !mode_is_signed(src_mode)) {
+                               panic("unsigned to float not lowered!");
+                       }
                        return create_itof(dbg, block, new_op, dst_mode);
                }
        } else { /* complete in gp registers */
@@ -1462,7 +1468,7 @@ static ir_node *gen_Call(ir_node *node)
        /* max inputs: memory, callee, register arguments */
        int              max_inputs   = 2 + n_param_regs;
        ir_node        **in           = ALLOCAN(ir_node*, max_inputs);
-       ir_node        **sync_ins     = ALLOCAN(ir_node*, max_inputs);
+       ir_node        **sync_ins     = ALLOCAN(ir_node*, n_params);
        struct obstack  *obst         = be_get_be_obst(irg);
        const arch_register_req_t **in_req
                = OALLOCNZ(obst, const arch_register_req_t*, max_inputs);
@@ -1584,7 +1590,7 @@ static ir_node *gen_Call(ir_node *node)
        } else {
                res = new_bd_sparc_Call_reg(dbgi, new_block, in_arity, in, out_arity);
        }
-       set_sparc_in_req_all(res, in_req);
+       arch_set_in_register_reqs(res, in_req);
 
        /* create output register reqs */
        o = 0;