C99 features removed
[libfirm] / ir / be / ia32 / ia32_common_transform.c
index 8859b83..5245bb9 100644 (file)
@@ -24,6 +24,9 @@
  * @author      Matthias Braun, Sebastian Buchwald
  * @version     $Id: ia32_common_transform.c 21012 2008-08-06 13:35:17Z beck $
  */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 
 #include "error.h"
 #include "irargs_t.h"
@@ -32,6 +35,7 @@
 #include "typerep.h"
 
 #include "../betranshlp.h"
+#include "../beirg_t.h"
 
 #include "ia32_architecture.h"
 #include "ia32_common_transform.h"
@@ -456,8 +460,8 @@ static void parse_asm_constraints(constraint_t *constraint, const char *c,
 ir_node *gen_ASM(ir_node *node)
 {
        ir_graph                   *irg       = current_ir_graph;
-       ir_node                    *block     = get_nodes_block(node);
-       ir_node                    *new_block = be_transform_node(block);
+       ir_node                    *block = NULL;
+       ir_node                    *new_block = NULL;
        dbg_info                   *dbgi      = get_irn_dbg_info(node);
        int                         i, arity;
        int                         out_idx;
@@ -475,7 +479,25 @@ ir_node *gen_ASM(ir_node *node)
        const ir_asm_constraint    *out_constraints;
        ident                     **clobbers;
        int                         clobbers_flags = 0;
-       unsigned                    clobber_bits_gp = 0;
+       unsigned                    clobber_bits[N_CLASSES];
+
+       memset(&clobber_bits, 0, sizeof(clobber_bits));
+
+       switch (be_transformer) {
+       case TRANSFORMER_DEFAULT:
+               block     = get_nodes_block(node);
+               new_block = be_transform_node(block);
+               break;
+
+#ifdef FIRM_GRGEN_BE
+       case TRANSFORMER_PBQP:
+               new_block = get_nodes_block(node);
+               break;
+#endif
+
+       default:
+               panic("invalid transformer");
+       }
 
        /* workaround for lots of buggy code out there as most people think volatile
         * asm is enough for everything and forget the flags (linux kernel, etc.)
@@ -490,7 +512,7 @@ ir_node *gen_ASM(ir_node *node)
 
        clobbers   = get_ASM_clobbers(node);
        n_clobbers = 0;
-       for(i = 0; i < get_ASM_n_clobbers(node); ++i) {
+       for (i = 0; i < get_ASM_n_clobbers(node); ++i) {
                const arch_register_req_t *req;
                const char                *c = get_id_str(clobbers[i]);
 
@@ -502,9 +524,7 @@ ir_node *gen_ASM(ir_node *node)
                }
 
                req = parse_clobber(c);
-               if (req->cls == &ia32_reg_classes[CLASS_ia32_gp]) {
-                       clobber_bits_gp |= *req->limited;
-               }
+               clobber_bits[req->cls->index] |= *req->limited;
 
                n_clobbers++;
        }
@@ -515,12 +535,12 @@ ir_node *gen_ASM(ir_node *node)
        out_constraints = get_ASM_output_constraints(node);
 
        /* determine size of register_map */
-       for(out_idx = 0; out_idx < n_out_constraints; ++out_idx) {
+       for (out_idx = 0; out_idx < n_out_constraints; ++out_idx) {
                const ir_asm_constraint *constraint = &out_constraints[out_idx];
                if (constraint->pos > reg_map_size)
                        reg_map_size = constraint->pos;
        }
-       for(i = 0; i < arity; ++i) {
+       for (i = 0; i < arity; ++i) {
                const ir_asm_constraint   *constraint = &in_constraints[i];
                if(constraint->pos > reg_map_size)
                        reg_map_size = constraint->pos;
@@ -534,7 +554,7 @@ ir_node *gen_ASM(ir_node *node)
        /* construct output constraints */
        out_reg_reqs = obstack_alloc(obst, out_arity * sizeof(out_reg_reqs[0]));
 
-       for(out_idx = 0; out_idx < n_out_constraints; ++out_idx) {
+       for (out_idx = 0; out_idx < n_out_constraints; ++out_idx) {
                const ir_asm_constraint   *constraint = &out_constraints[out_idx];
                const char                *c       = get_id_str(constraint->constraint);
                unsigned                   pos        = constraint->pos;
@@ -555,7 +575,7 @@ ir_node *gen_ASM(ir_node *node)
 
        /* inputs + input constraints */
        in_reg_reqs = obstack_alloc(obst, arity * sizeof(in_reg_reqs[0]));
-       for(i = 0; i < arity; ++i) {
+       for (i = 0; i < arity; ++i) {
                ir_node                   *pred         = get_irn_n(node, i);
                const ir_asm_constraint   *constraint   = &in_constraints[i];
                ident                     *constr_id    = constraint->constraint;
@@ -563,24 +583,22 @@ ir_node *gen_ASM(ir_node *node)
                unsigned                   pos          = constraint->pos;
                int                        is_memory_op = 0;
                ir_node                   *input        = NULL;
+               unsigned                   r_clobber_bits;
                constraint_t               parsed_constraint;
                const arch_register_req_t *req;
 
                parse_asm_constraints(&parsed_constraint, c, 0);
-               if (clobber_bits_gp != 0 &&
-                   parsed_constraint.cls == &ia32_reg_classes[CLASS_ia32_gp]) {
-                       if (parsed_constraint.all_registers_allowed) {
-                               parsed_constraint.all_registers_allowed = 0;
-                               parsed_constraint.allowed_registers     =
-                                       1 << REG_EAX |
-                                       1 << REG_EBX |
-                                       1 << REG_ECX |
-                                       1 << REG_EDX |
-                                       1 << REG_ESI |
-                                       1 << REG_EDI |
-                                       1 << REG_EBP;
+               if (parsed_constraint.cls != NULL) {
+                       r_clobber_bits = clobber_bits[parsed_constraint.cls->index];
+                       if (r_clobber_bits != 0) {
+                               if (parsed_constraint.all_registers_allowed) {
+                                       parsed_constraint.all_registers_allowed = 0;
+                                       be_abi_set_non_ignore_regs(env_cg->birg->abi,
+                                                       parsed_constraint.cls,
+                                                       &parsed_constraint.allowed_registers);
+                               }
+                               parsed_constraint.allowed_registers &= ~r_clobber_bits;
                        }
-                       parsed_constraint.allowed_registers &= ~clobber_bits_gp;
                }
 
                req = make_register_req(&parsed_constraint, n_out_constraints,
@@ -593,8 +611,21 @@ ir_node *gen_ASM(ir_node *node)
                }
 
                if (input == NULL) {
-                       ir_node *pred = get_irn_n(node, i);
-                       input         = be_transform_node(pred);
+                       ir_node *pred = NULL;
+                       switch (be_transformer) {
+                       case TRANSFORMER_DEFAULT:
+                               pred  = get_irn_n(node, i);
+                               input = be_transform_node(pred);
+                               break;
+
+#ifdef FIRM_GRGEN_BE
+                       case TRANSFORMER_PBQP:
+                               input = get_irn_n(node, i);
+                               break;
+#endif
+
+                       default: panic("invalid transformer");
+                       }
 
                        if (parsed_constraint.cls == NULL
                                        && parsed_constraint.same_as < 0) {
@@ -613,7 +644,7 @@ ir_node *gen_ASM(ir_node *node)
        }
 
        /* parse clobbers */
-       for(i = 0; i < get_ASM_n_clobbers(node); ++i) {
+       for (i = 0; i < get_ASM_n_clobbers(node); ++i) {
                const char                *c = get_id_str(clobbers[i]);
                const arch_register_req_t *req;
 
@@ -636,6 +667,66 @@ ir_node *gen_ASM(ir_node *node)
        return new_node;
 }
 
+ir_node *gen_CopyB(ir_node *node) {
+       ir_node  *block    = NULL;
+       ir_node  *src      = NULL;
+       ir_node  *new_src  = NULL;
+       ir_node  *dst      = NULL;
+       ir_node  *new_dst  = NULL;
+       ir_node  *mem      = NULL;
+       ir_node  *new_mem  = NULL;
+       ir_node  *res      = NULL;
+       ir_graph *irg      = current_ir_graph;
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       int      size      = get_type_size_bytes(get_CopyB_type(node));
+       int      rem;
+
+       switch (be_transformer) {
+               case TRANSFORMER_DEFAULT:
+                       block    = be_transform_node(get_nodes_block(node));
+                       src      = get_CopyB_src(node);
+                       new_src  = be_transform_node(src);
+                       dst      = get_CopyB_dst(node);
+                       new_dst  = be_transform_node(dst);
+                       mem      = get_CopyB_mem(node);
+                       new_mem  = be_transform_node(mem);
+                       break;
+
+#ifdef FIRM_GRGEN_BE
+               case TRANSFORMER_PBQP:
+                       block    = get_nodes_block(node);
+                       new_src  = get_CopyB_src(node);
+                       new_dst  = get_CopyB_dst(node);
+                       new_mem  = get_CopyB_mem(node);
+                       break;
+#endif
+
+               default: panic("invalid transformer");
+       }
+
+       /* If we have to copy more than 32 bytes, we use REP MOVSx and */
+       /* then we need the size explicitly in ECX.                    */
+       if (size >= 32 * 4) {
+               rem = size & 0x3; /* size % 4 */
+               size >>= 2;
+
+               res = new_rd_ia32_Const(dbgi, irg, block, NULL, 0, size);
+               add_irn_dep(res, get_irg_frame(irg));
+
+               res = new_rd_ia32_CopyB(dbgi, irg, block, new_dst, new_src, res, new_mem, rem);
+       } else {
+               if(size == 0) {
+                       ir_fprintf(stderr, "Optimization warning copyb %+F with size <4\n",
+                                  node);
+               }
+               res = new_rd_ia32_CopyB_i(dbgi, irg, block, new_dst, new_src, new_mem, size);
+       }
+
+       SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
+
+       return res;
+}
+
 ir_node *gen_Unknown(ir_node *node)
 {
        ir_mode *mode = get_irn_mode(node);