move backend into libfirm
[libfirm] / ir / be / arm / arm_transform.c
index e665bb4..91e75e3 100644 (file)
@@ -1,4 +1,4 @@
-/* The codegenrator (transform FIRM into arm FIRM */
+/* The codegenerator (transform FIRM into arm FIRM */
 /* $Id$ */
 
 #ifdef HAVE_CONFIG_H
@@ -139,7 +139,6 @@ unsigned int arm_decode_imm_w_shift(tarval *tv) {
  */
 static ir_node *create_const_graph_value(ir_node *irn, ir_node *block, unsigned int value) {
        ir_node *result;
-       int negate = 0;
        vals v, vn;
        int cnt;
        ir_mode *mode = get_irn_mode(irn);
@@ -182,24 +181,25 @@ static ir_node *create_const_graph(ir_node *irn, ir_node *block) {
 }
 
 
-
+/**
+ * Creates code for a Firm Const node.
+ */
 static ir_node *gen_Const(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *result;
        ir_graph *irg = current_ir_graph;
        ir_node *block = get_nodes_block(irn);
        ir_mode *mode = get_irn_mode(irn);
        dbg_info *dbg = get_irn_dbg_info(irn);
 
-       assert(mode != mode_E && "IEEE Extended FP not supported");
-       if (mode == mode_F)
-               result = new_rd_arm_fConst(dbg, irg, block, mode, get_Const_tarval(irn));
-       else if (mode == mode_D)
-               result = new_rd_arm_fConst(dbg, irg, block, mode, get_Const_tarval(irn));
-       else if (mode == mode_P)
+       if (mode_is_float(mode)) {
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaConst(dbg, irg, block, mode, get_Const_tarval(irn));
+               else if (USE_VFP(cg->isa))
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               assert(0 && "NYI");
+       }
+       else if (mode_is_reference(mode))
                return irn;
-       else
-               result = create_const_graph(irn, block);
-       return result;
+       return create_const_graph(irn, block);
 }
 
 static ir_node *gen_mask(ir_node *irn, ir_node *op, int result_bits) {
@@ -235,21 +235,34 @@ static ir_node *gen_Conv(ir_node *irn, arm_code_gen_t *cg) {
        ir_mode *out_mode = get_irn_mode(irn);
        dbg_info *dbg    = get_irn_dbg_info(irn);
 
-       assert( in_mode != mode_E && "");
-       assert( in_mode != mode_Ls && "");
-       assert( in_mode != mode_Lu && "");
-       assert( out_mode != mode_E && "");
-       assert( out_mode != mode_Ls && "");
-       assert( out_mode != mode_Lu && "");
-
        if (in_mode == out_mode)
                return op;
 
-       if ((mode_is_int(in_mode) || mode_is_reference(in_mode))
-               && (mode_is_reference(out_mode) || mode_is_int(out_mode))) {
-               int in_bits = get_mode_size_bits(in_mode);
+       if (mode_is_float(in_mode) || mode_is_float(out_mode)) {
+               cg->have_fp = 1;
+
+               if (USE_FPA(cg->isa)) {
+                       if (mode_is_float(in_mode)) {
+                               if (mode_is_float(out_mode)) {
+                                       /* from float to float */
+                                       return new_rd_arm_fpaMov(dbg, irg, block, op, out_mode);
+                               }
+                               else {
+                                       /* from float to int */
+                                       return new_rd_arm_fpaFix(dbg, irg, block, op, out_mode);
+                               }
+                       }
+                       else {
+                               /* from int to float */
+                               return new_rd_arm_fpaFlt(dbg, irg, block, op, out_mode);
+                       }
+               }
+               assert(0 && "NYI");
+       }
+       else { /* complete in gp registers */
+               int in_bits  = get_mode_size_bits(in_mode);
                int out_bits = get_mode_size_bits(out_mode);
-               int in_sign = get_mode_sign(in_mode);
+               int in_sign  = get_mode_sign(in_mode);
                int out_sign = get_mode_sign(out_mode);
 
                // 32 -> 32
@@ -309,20 +322,8 @@ static ir_node *gen_Conv(ir_node *irn, arm_code_gen_t *cg) {
                }
                assert(0 && "recheck integer conversion logic!");
                return irn;
-       } else if (in_mode == mode_D && out_mode == mode_F) {
-               return new_rd_arm_fConvD2S(dbg, irg, block, op, out_mode);
-       } else if (in_mode == mode_F && out_mode == mode_D) {
-               return new_rd_arm_fConvS2D(dbg, irg, block, op, out_mode);
-       } else if (mode_is_int(in_mode) && mode_is_float(out_mode)) {
-               cg->have_fp = 1;
-               return irn; /* TODO: implement int->float conversion*/
-       } else if (mode_is_float(in_mode) && mode_is_int(out_mode)) {
-               cg->have_fp = 1;
-               return irn; /* TODO: implement float->int conversion*/
-       } else {
-               assert(0 && "not implemented conversion");
-               return irn;
        }
+       return NULL;
 }
 
 /**
@@ -360,11 +361,14 @@ static ir_node *gen_Add(ir_node *irn, arm_code_gen_t *cg) {
        arm_shift_modifier mod;
        dbg_info *dbg = get_irn_dbg_info(irn);
 
-       assert(mode != mode_E && "IEEE Extended FP not supported");
-
        if (mode_is_float(mode)) {
                cg->have_fp = 1;
-               return new_rd_arm_fAdd(dbg, irg, block, op1, op2, mode);
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaAdd(dbg, irg, block, op1, op2, mode);
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        if (mode_is_numP(mode)) {
                if (is_arm_Mov_i(op1))
@@ -423,11 +427,14 @@ static ir_node *gen_Mul(ir_node *irn, arm_code_gen_t *cg) {
        ir_graph *irg = current_ir_graph;
        dbg_info *dbg = get_irn_dbg_info(irn);
 
-       assert(mode != mode_E && "IEEE Extended FP not supported");
-
        if (mode_is_float(mode)) {
                cg->have_fp = 1;
-               return new_rd_arm_fMul(dbg, irg, block, op1, op2, mode);
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaMul(dbg, irg, block, op1, op2, mode);
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        return new_rd_arm_Mul(dbg, irg, block, op1, op2, mode);
 }
@@ -447,7 +454,15 @@ static ir_node *gen_Quot(ir_node *irn, arm_code_gen_t *cg) {
 
        assert(mode != mode_E && "IEEE Extended FP not supported");
 
-       return new_rd_arm_fDiv(dbg, current_ir_graph, block, op1, op2, mode);
+       cg->have_fp = 1;
+       if (USE_FPA(cg->isa))
+               return new_rd_arm_fpaDiv(dbg, current_ir_graph, block, op1, op2, mode);
+       else if (USE_VFP(cg->isa)) {
+               assert(mode != mode_E && "IEEE Extended FP not supported");
+       }
+       assert(0 && "NYI");
+
+       return NULL;
 }
 
 #define GEN_INT_OP(op) \
@@ -525,11 +540,14 @@ static ir_node *gen_Sub(ir_node *irn, arm_code_gen_t *cg) {
        ir_graph *irg = current_ir_graph;
        dbg_info *dbg = get_irn_dbg_info(irn);
 
-       assert(mode != mode_E && "IEEE Extended FP not supported");
-
        if (mode_is_float(mode)) {
                cg->have_fp = 1;
-               return new_rd_arm_fSub(dbg, irg, block, op1, op2, mode);
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaSub(dbg, irg, block, op1, op2, mode);
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        if (mode_is_numP(mode)) {
                if (is_arm_Mov_i(op1))
@@ -658,11 +676,14 @@ static ir_node *gen_Abs(ir_node *irn, arm_code_gen_t *cg) {
        ir_mode *mode = get_irn_mode(irn);
        dbg_info *dbg = get_irn_dbg_info(irn);
 
-       assert(mode != mode_E && "IEEE Extended FP not supported");
-
        if (mode_is_float(mode)) {
                cg->have_fp = 1;
-               return new_rd_arm_fAbs(dbg, current_ir_graph, block, op, mode);
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaAbs(dbg, current_ir_graph, block, op, mode);
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        return new_rd_arm_Abs(dbg, current_ir_graph, block, op, mode);
 }
@@ -681,7 +702,13 @@ static ir_node *gen_Minus(ir_node *irn, arm_code_gen_t *cg) {
        dbg_info *dbg = get_irn_dbg_info(irn);
 
        if (mode_is_float(mode)) {
-               return new_rd_arm_fNeg(dbg, irg, block, op, mode);
+               cg->have_fp = 1;
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaMnv(dbg, irg, block, op, mode);
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        return new_rd_arm_Rsb_i(dbg, irg, block, op, mode, get_mode_null(mode));
 }
@@ -703,8 +730,13 @@ static ir_node *gen_Load(ir_node *irn, arm_code_gen_t *cg) {
 
        if (mode_is_float(mode)) {
                cg->have_fp = 1;
-               /* FIXME: set the load mode */
-               return new_rd_arm_fLoad(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaLdf(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn),
+                               get_Load_mode(irn));
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        if (mode == mode_Bu) {
                return new_rd_arm_Loadb(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
@@ -742,8 +774,13 @@ static ir_node *gen_Store(ir_node *irn, arm_code_gen_t *cg) {
        assert(mode != mode_E && "IEEE Extended FP not supported");
        if (mode_is_float(mode)) {
                cg->have_fp = 1;
-               /* FIXME: set the store mode */
-               return new_rd_arm_fStore(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaStf(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn),
+                               get_Store_mem(irn), get_irn_mode(get_Store_value(irn)));
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        if (mode == mode_Bu) {
                return new_rd_arm_Storeb(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
@@ -913,23 +950,23 @@ static ir_node *gen_CopyB(ir_node *irn, arm_code_gen_t *cg) {
  * access must be done relative the the fist IncSP ...
  */
 static int get_sp_expand_offset(ir_node *inc_sp) {
-       unsigned offset    = be_get_IncSP_offset(inc_sp);
-       be_stack_dir_t dir = be_get_IncSP_direction(inc_sp);
+       int offset = be_get_IncSP_offset(inc_sp);
 
-       if (offset == BE_STACK_FRAME_SIZE)
+       if (offset == BE_STACK_FRAME_SIZE_EXPAND)
                return 0;
-       return dir == be_stack_dir_expand ? (int)offset : -(int)offset;
+
+       return offset;
 }
 
-static ir_node *gen_StackParam(ir_node *irn, arm_code_gen_t *cg) {
 #if 0
-       ir_node *new_op = NULL;
-       ir_node *block  = get_nodes_block(irn);
-       ir_node *noreg  = ia32_new_NoReg_gp(env->cg);
-       ir_node *mem    = new_rd_NoMem(env->irg);
-       ir_node *ptr    = get_irn_n(irn, 0);
-       entity  *ent    = be_get_frame_entity(irn);
-       ir_mode *mode   = env->mode;
+static ir_node *gen_StackParam(ir_node *irn, arm_code_gen_t *cg) {
+       ir_node   *new_op = NULL;
+       ir_node   *block  = get_nodes_block(irn);
+       ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
+       ir_node   *mem    = new_rd_NoMem(env->irg);
+       ir_node   *ptr    = get_irn_n(irn, 0);
+       ir_entity *ent    = be_get_frame_entity(irn);
+       ir_mode   *mode   = env->mode;
 
 //     /* If the StackParam has only one user ->     */
 //     /* put it in the Block where the user resides */
@@ -960,16 +997,16 @@ static ir_node *gen_StackParam(ir_node *irn, arm_code_gen_t *cg) {
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
 
        return new_rd_Proj(env->dbg, env->irg, block, new_op, mode, 0);
-#endif
 }
+#endif
 
 /**
  * Transforms a FrameAddr into an ia32 Add.
  */
 static ir_node *gen_be_FrameAddr(ir_node *irn, arm_code_gen_t *cg) {
        ir_node *block  = get_nodes_block(irn);
-       entity  *ent    = be_get_frame_entity(irn);
-       int     offset  = get_entity_offset_bytes(ent);
+       ir_entity *ent  = be_get_frame_entity(irn);
+       int     offset  = get_entity_offset(ent);
        ir_node *op     = get_irn_n(irn, 0);
        ir_node *cnst;
        ir_mode *mode   = get_irn_mode(irn);
@@ -986,17 +1023,17 @@ static ir_node *gen_be_FrameAddr(ir_node *irn, arm_code_gen_t *cg) {
        return new_rd_arm_Add(dbg, current_ir_graph, block, op, cnst, mode, ARM_SHF_NONE, NULL);
 }
 
+#if 0
 /**
  * Transforms a FrameLoad into an ia32 Load.
  */
 static ir_node *gen_FrameLoad(ir_node *irn, arm_code_gen_t *cg) {
-#if 0
-       ir_node *new_op = NULL;
-       ir_node *noreg  = ia32_new_NoReg_gp(env->cg);
-       ir_node *mem    = get_irn_n(irn, 0);
-       ir_node *ptr    = get_irn_n(irn, 1);
-       entity  *ent    = be_get_frame_entity(irn);
-       ir_mode *mode   = get_type_mode(get_entity_type(ent));
+       ir_node   *new_op = NULL;
+       ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
+       ir_node   *mem    = get_irn_n(irn, 0);
+       ir_node   *ptr    = get_irn_n(irn, 1);
+       ir_entity *ent    = be_get_frame_entity(irn);
+       ir_mode   *mode   = get_type_mode(get_entity_type(ent));
 
        if (mode_is_float(mode)) {
                if (USE_SSE2(env->cg))
@@ -1021,22 +1058,21 @@ static ir_node *gen_FrameLoad(ir_node *irn, arm_code_gen_t *cg) {
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
 
        return new_op;
-#endif
 }
+#endif
 
-
+#if 0
 /**
  * Transforms a FrameStore into an ia32 Store.
  */
 static ir_node *gen_FrameStore(ir_node *irn, arm_code_gen_t *cg) {
-#if 0
-       ir_node *new_op = NULL;
-       ir_node *noreg  = ia32_new_NoReg_gp(env->cg);
-       ir_node *mem    = get_irn_n(irn, 0);
-       ir_node *ptr    = get_irn_n(irn, 1);
-       ir_node *val    = get_irn_n(irn, 2);
-       entity  *ent    = be_get_frame_entity(irn);
-       ir_mode *mode   = get_irn_mode(val);
+       ir_node   *new_op = NULL;
+       ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
+       ir_node   *mem    = get_irn_n(irn, 0);
+       ir_node   *ptr    = get_irn_n(irn, 1);
+       ir_node   *val    = get_irn_n(irn, 2);
+       ir_entity *ent    = be_get_frame_entity(irn);
+       ir_mode   *mode   = get_irn_mode(val);
 
        if (mode_is_float(mode)) {
                if (USE_SSE2(env->cg))
@@ -1064,8 +1100,8 @@ static ir_node *gen_FrameStore(ir_node *irn, arm_code_gen_t *cg) {
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
 
        return new_op;
-#endif
 }
+#endif
 
 
 // static ir_node *gen_be_Copy(ir_node *irn, arm_code_gen_t *cg) {
@@ -1082,25 +1118,28 @@ static ir_node *gen_FrameStore(ir_node *irn, arm_code_gen_t *cg) {
  *
  *********************************************************/
 
-/************************************************************************/
-/* move constants out of startblock                                       */
-/************************************************************************/
+/**
+ * move constants out of the start block
+ */
 void arm_move_consts(ir_node *node, void *env) {
-       arm_code_gen_t *cgenv = (arm_code_gen_t *)env;
        int i;
 
        if (is_Block(node))
                return;
 
        if (is_Phi(node)) {
-               for (i = 0; i < get_irn_arity(node); i++) {
+               for (i = get_irn_arity(node) - 1; i >= 0; --i) {
                        ir_node *pred = get_irn_n(node,i);
-                       opcode pred_code = get_irn_opcode(pred);
+                       ir_opcode pred_code = get_irn_opcode(pred);
                        if (pred_code == iro_Const) {
                                ir_node *const_graph;
                                const_graph = create_const_graph(pred, get_nodes_block(get_irn_n(get_nodes_block(node),i)));
                                set_irn_n(node, i, const_graph);
-                       } else if (pred_code == iro_SymConst) {
+                       }
+                       else if (pred_code == iro_SymConst) {
+                               /* FIXME: in general, SymConst always require a load, so it
+                                  might be better to place them into the first real block
+                                  and let the spiller rematerialize them. */
                                const char *str = get_sc_name(pred);
                                ir_node *symconst_node;
                                symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
@@ -1113,7 +1152,7 @@ void arm_move_consts(ir_node *node, void *env) {
        }
        for (i = 0; i < get_irn_arity(node); i++) {
                ir_node *pred = get_irn_n(node,i);
-               opcode pred_code = get_irn_opcode(pred);
+               ir_opcode pred_code = get_irn_opcode(pred);
                if (pred_code == iro_Const) {
                        ir_node *const_graph;
                        const_graph = create_const_graph(pred, get_nodes_block(node));
@@ -1140,8 +1179,8 @@ void arm_move_symconsts(ir_node *node, void *env) {
                return;
 
        for (i = 0; i < get_irn_arity(node); i++) {
-               ir_node *pred      = get_irn_n(node,i);
-               opcode   pred_code = get_irn_opcode(pred);
+               ir_node *pred       = get_irn_n(node,i);
+               ir_opcode pred_code = get_irn_opcode(pred);
 
                if (pred_code == iro_SymConst) {
                        const char *str = get_sc_name(pred);