fixed some bugs
[libfirm] / ir / be / ia32 / ia32_transform.c
index 569b6de..994b020 100644 (file)
@@ -5,12 +5,14 @@
 #include "irnode_t.h"
 #include "irgraph_t.h"
 #include "irmode_t.h"
+#include "iropt_t.h"
+#include "irop_t.h"
+#include "irprog_t.h"
 #include "irgmod.h"
 #include "iredges.h"
 #include "irvrfy.h"
 #include "ircons.h"
 #include "dbginfo.h"
-#include "iropt_t.h"
 #include "debug.h"
 
 #include "../benode_t.h"
@@ -20,7 +22,6 @@
 #include "../arch/archop.h"     /* we need this for Min and Max nodes */
 #include "ia32_transform.h"
 #include "ia32_new_nodes.h"
-#include "ia32_map_regs.h"
 
 #include "gen_ia32_regalloc_if.h"
 
@@ -146,19 +147,17 @@ static char *gen_fp_known_const(ir_mode *mode, ia32_known_const_t kct) {
 }
 
 
-#undef is_cnst
-#define is_cnst(op) (is_ia32_Const(op) || is_ia32_fConst(op))
 
 /* determine if one operator is an Imm */
 static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
        if (op1)
-               return is_cnst(op1) ? op1 : (is_cnst(op2) ? op2 : NULL);
-       else return is_cnst(op2) ? op2 : NULL;
+               return is_ia32_Cnst(op1) ? op1 : (is_ia32_Cnst(op2) ? op2 : NULL);
+       else return is_ia32_Cnst(op2) ? op2 : NULL;
 }
 
 /* determine if one operator is not an Imm */
 static ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
-       return !is_cnst(op1) ? op1 : (!is_cnst(op2) ? op2 : NULL);
+       return !is_ia32_Cnst(op1) ? op1 : (!is_ia32_Cnst(op2) ? op2 : NULL);
 }
 
 
@@ -184,8 +183,13 @@ static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2,
        ir_node           *expr_op, *imm_op;
 
 
-       /* check if it's an operation with immediate */
-       if (is_op_commutative(get_irn_op(env->irn))) {
+       /* Check if immediate optimization is on and */
+       /* if it's an operation with immediate.      */
+       if (! env->cg->opt.immops) {
+               expr_op = op1;
+               imm_op  = NULL;
+       }
+       else if (is_op_commutative(get_irn_op(env->irn))) {
                imm_op  = get_immediate_op(op1, op2);
                expr_op = get_expr_op(op1, op2);
        }
@@ -232,6 +236,10 @@ static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2,
                }
        }
 
+       if (is_op_commutative(get_irn_op(env->irn))) {
+               set_ia32_commutative(new_op);
+       }
+
        return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
 }
 
@@ -260,7 +268,9 @@ static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node
 
        assert(! mode_is_float(mode) && "Shift/Rotate with float not supported");
 
-       imm_op  = get_immediate_op(NULL, op2);
+       /* Check if immediate optimization is on and */
+       /* if it's an operation with immediate.      */
+       imm_op  = env->cg->opt.immops ? get_immediate_op(NULL, op2) : NULL;
        expr_op = get_expr_op(op1, op2);
 
        assert((expr_op || imm_op) && "invalid operands");
@@ -354,8 +364,8 @@ static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node
        int                     normal_add = 1;
        tarval_classification_t class_tv, class_negtv;
 
-       /* const_op: tarval or SymConst? */
-       if (tv) {
+       /* try to optimize to inc/dec  */
+       if (env->cg->opt.incdec && tv) {
                /* optimize tarvals */
                class_tv    = classify_tarval(tv);
                class_negtv = classify_tarval(tarval_neg(tv));
@@ -400,7 +410,9 @@ static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
        ir_node  *nomem  = new_NoMem();
        ir_node  *expr_op, *imm_op;
 
-       imm_op  = get_immediate_op(op1, op2);
+       /* Check if immediate optimization is on and */
+       /* if it's an operation with immediate.      */
+       imm_op  = env->cg->opt.immops ? get_immediate_op(op1, op2) : NULL;
        expr_op = get_expr_op(op1, op2);
 
        assert((expr_op || imm_op) && "invalid operands");
@@ -458,7 +470,7 @@ static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
  * @param mode      node mode
  * @return the created ia32 Mul node
  */
-ir_node *gen_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
+static ir_node *gen_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
        ir_node *new_op;
 
        if (mode_is_float(env->mode)) {
@@ -640,8 +652,8 @@ static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node
        int                     normal_sub = 1;
        tarval_classification_t class_tv, class_negtv;
 
-       /* const_op: tarval or SymConst? */
-       if (tv) {
+       /* try to optimize to inc/dec  */
+       if (env->cg->opt.incdec && tv) {
                /* optimize tarvals */
                class_tv    = classify_tarval(tv);
                class_negtv = classify_tarval(tarval_neg(tv));
@@ -684,7 +696,9 @@ static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
        ir_node  *nomem  = new_NoMem();
        ir_node  *expr_op, *imm_op;
 
-       imm_op  = get_immediate_op(NULL, op2);
+       /* Check if immediate optimization is on and */
+       /* if it's an operation with immediate.      */
+       imm_op  = env->cg->opt.immops ? get_immediate_op(NULL, op2) : NULL;
        expr_op = get_expr_op(op1, op2);
 
        assert((expr_op || imm_op) && "invalid operands");
@@ -1107,6 +1121,8 @@ static ir_node *gen_Load(ia32_transform_env_t *env) {
        }
 
        set_ia32_am_support(new_op, ia32_am_Source);
+       set_ia32_op_type(new_op, ia32_AddrModeS);
+       set_ia32_am_flavour(new_op, ia32_B);
        set_ia32_ls_mode(new_op, get_Load_mode(node));
 
        return new_op;
@@ -1123,20 +1139,36 @@ static ir_node *gen_Load(ia32_transform_env_t *env) {
  * @param mode    node mode
  * @return the created ia32 Store node
  */
-ir_node *gen_Store(ia32_transform_env_t *env) {
+static ir_node *gen_Store(ia32_transform_env_t *env) {
        ir_node *node  = env->irn;
        ir_node *noreg = ia32_new_NoReg_gp(env->cg);
+       ir_node *val   = get_Store_value(node);
+       ir_node *ptr   = get_Store_ptr(node);
+       ir_node *mem   = get_Store_mem(node);
+       ir_node *sval  = val;
        ir_node *new_op;
 
+       /* in case of storing a const -> make it an attribute */
+       if (is_ia32_Cnst(val)) {
+               sval = noreg;
+       }
+
        if (mode_is_float(env->mode)) {
-               new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, get_Store_ptr(node), noreg, get_Store_value(node), get_Store_mem(node), env->mode);
+               new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, env->mode);
        }
        else {
-               new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), noreg, get_Store_value(node), get_Store_mem(node), env->mode);
+               new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, env->mode);
+       }
+
+       /* stored const is an attribute (saves a register) */
+       if (is_ia32_Cnst(val)) {
+               set_ia32_Immop_attr(new_op, val);
        }
 
        set_ia32_am_support(new_op, ia32_am_Dest);
-       set_ia32_ls_mode(new_op, get_irn_mode(get_Store_value(node)));
+       set_ia32_op_type(new_op, ia32_AddrModeD);
+       set_ia32_am_flavour(new_op, ia32_B);
+       set_ia32_ls_mode(new_op, get_irn_mode(val));
        return new_op;
 }
 
@@ -1145,128 +1177,10 @@ ir_node *gen_Store(ia32_transform_env_t *env) {
 /**
  * Transforms a Call and its arguments corresponding to the calling convention.
  *
- * @param mod     the debug module
- * @param block   the block the new node should belong to
- * @param node    the ir Call node
- * @param dummy   mode doesn't matter
- * @return the created ia32 Call node
+ * @param env   The transformation environment
+ * @return The created ia32 Call node
  */
 static ir_node *gen_Call(ia32_transform_env_t *env) {
-#if 0
-       const ia32_register_req_t **in_req;
-       ir_node          **in;
-       ir_node           *new_call, *sync;
-       int                i, j, n_new_call_in, ignore = 0;
-       ia32_attr_t       *attr;
-       dbg_info          *dbg          = env->dbg;
-       ir_graph          *irg          = env->irg;
-       ir_node           *block        = env->block;
-       ir_node           *call         = env->irn;
-       ir_node          **stack_param  = NULL;
-       ir_node          **param        = get_Call_param_arr(call);
-       ir_node           *call_Mem     = get_Call_mem(call);
-       unsigned           cc           = get_method_calling_convention(get_Call_type(call));
-       int                n            = get_Call_n_params(call);
-       int                stack_idx    = 0;
-       int                biggest_n    = -1;
-       int                n_res        = get_method_n_ress(get_Call_type(call));
-
-       assert(n_res <= 2 && "method with more than two results not supported");
-
-       if (cc & cc_reg_param)
-               biggest_n = ia32_get_n_regparam_class(n, param, &ignore, &ignore);
-
-       /* remember: biggest_n = x means we can pass (x + 1) parameters in register */
-
-       /* do we need to pass arguments on stack? */
-       if (biggest_n + 1 < n)
-               stack_param = xcalloc(n - biggest_n - 1, sizeof(ir_node *));
-
-       /* we need at least one in, either for the stack params or the call_Mem */
-       n_new_call_in = biggest_n + 2;
-
-       /* the call has one IN for all stack parameter and one IN for each reg param */
-       in     = xcalloc(n_new_call_in, sizeof(ir_node *));
-       in_req = xcalloc(n_new_call_in, sizeof(arch_register_req_t *));
-
-       /* loop over all parameters and set the register requirements */
-       for (i = 0; i <= biggest_n && (cc & cc_reg_param); i++) {
-               in_req[i] = ia32_get_RegParam_req(n, param, i, cc);
-       }
-       stack_idx = i;
-
-       /* create remaining stack parameters */
-       if (cc & cc_last_on_top) {
-               for (i = stack_idx; i < n; i++) {
-                       /* pass it on stack */
-                       if (mode_is_float(get_irn_mode(param[i]))) {
-                               stack_param[i - stack_idx] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), irg,
-                                                                                                               block, call_Mem, param[i], mode_M);
-                       }
-                       else {
-                               stack_param[i - stack_idx] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), irg,
-                                                                                                               block, call_Mem, param[i], mode_M);
-                       }
-                       /* set the argument number for later lowering */
-                       set_ia32_pncode(stack_param[i - stack_idx], i - stack_idx);
-               }
-       }
-       else {
-               for (i = n - 1, j = 0; i >= stack_idx; i--, j++) {
-                       /* pass it on stack */
-                       if (mode_is_float(get_irn_mode(param[i]))) {
-                               stack_param[j] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), irg,
-                                                                                                               block, call_Mem, param[i], mode_M);
-                       }
-                       else {
-                               stack_param[j] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), irg,
-                                                                                                               block, call_Mem, param[i], mode_M);
-                       }
-                       /* set the argument number for later lowering */
-                       set_ia32_pncode(stack_param[j], j);
-               }
-       }
-
-       if (stack_param) {
-               sync = new_r_Sync(irg, block, n - biggest_n - 1, stack_param);
-               in[n_new_call_in - 1] = sync;
-       }
-       else {
-               in[n_new_call_in - 1] = call_Mem;
-       }
-
-       /* create the new node */
-       new_call = new_rd_ia32_Call(dbg, irg, block, n_new_call_in, in);
-       set_ia32_Immop_attr(new_call, get_Call_ptr(call));
-
-       /* set register requirements for in and out */
-       attr             = get_ia32_attr(new_call);
-       attr->in_req     = in_req;
-
-       set_ia32_n_res(new_call, n_res);
-
-       if (n_res > 0) {
-               attr->out_req    = xcalloc(n_res, sizeof(ia32_register_req_t *));
-               attr->slots      = xcalloc(n_res, sizeof(arch_register_t *));
-       }
-
-       /* two results only appear when a 64bit int result is broken up into two 32bit results */
-       if (n_res == 1) {
-               if (mode_is_float(get_type_mode(get_method_res_type(get_Call_type(call), 0))))
-                       attr->out_req[0] = &ia32_default_req_ia32_fp_xmm0;
-               else
-                       attr->out_req[0] = &ia32_default_req_ia32_gp_eax;
-       }
-       else if (n_res == 2) {
-               attr->out_req[0] = &ia32_default_req_ia32_gp_eax;
-               attr->out_req[1] = &ia32_default_req_ia32_gp_edx;
-       }
-
-       /* stack parameter has no OUT register */
-       attr->in_req[n_new_call_in - 1] = &ia32_default_req_none;
-
-       return new_call;
-#endif
 }
 
 
@@ -1298,7 +1212,7 @@ static ir_node *gen_Cond(ia32_transform_env_t *env) {
                cmp_b = get_Cmp_right(pred);
 
                /* check if we can use a CondJmp with immediate */
-               cnst = get_immediate_op(cmp_a, cmp_b);
+               cnst = env->cg->opt.immops ? get_immediate_op(cmp_a, cmp_b) : NULL;
                expr = get_expr_op(cmp_a, cmp_b);
 
                if (cnst && expr) {
@@ -1310,9 +1224,10 @@ static ir_node *gen_Cond(ia32_transform_env_t *env) {
                }
 
                set_ia32_pncode(res, get_Proj_proj(sel));
+               set_ia32_am_support(res, ia32_am_Source);
        }
        else {
-               res = new_rd_ia32_SwitchJmp(dbg, irg, block, noreg, noreg, sel, nomem, mode_T);
+               res = new_rd_ia32_SwitchJmp(dbg, irg, block, sel, mode_T);
                set_ia32_pncode(res, get_Cond_defaultProj(node));
        }
 
@@ -1322,131 +1237,98 @@ static ir_node *gen_Cond(ia32_transform_env_t *env) {
 
 
 /**
- * Transform the argument projs from a start node corresponding to the
- * calling convention.
- * It transforms "Proj Arg x -> ProjT -> Start <- ProjM" into
- * "RegParam x   -> ProjT -> Start" OR
- * "StackParam x -> ProjM -> Start"
- * whether parameter is passed in register or on stack.
+ * Transforms a CopyB node.
  *
- * @param mod     the debug module
- * @param block   the block the nodes should belong to
- * @param proj    the ProjT node which points to Start
- * @param start   the Start node
- * @return Should be always NULL
+ * @param env   The transformation environment
+ * @return The transformed node.
  */
-static ir_node *gen_Proj_Start(ia32_transform_env_t *env, ir_node *proj, ir_node *start) {
-#if 0
-       const ia32_register_req_t *temp_req;
-       const ir_edge_t   *edge;
-       ir_node           *succ, *irn;
-       ir_node          **projargs;
-       ir_mode           *mode;
-       int                n, i;
-       unsigned           cc;
-       ir_node           *proj_M     = get_irg_initial_mem(current_ir_graph);
-       entity            *irg_ent    = get_irg_entity(current_ir_graph);
-       ir_type           *tp         = get_entity_type(irg_ent);
-       int                cur_pn     = 0;
-       ir_graph          *irg        = env->irg;
-       ir_node           *block      = env->block;
-
-       assert(is_Method_type(tp) && "irg type is not a method");
-
-       switch(get_Proj_proj(proj)) {
-               case pn_Start_T_args:
-                       /* We cannot use get_method_n_params here as the function might
-                          be variadic or one argument is not used. */
-                       n = get_irn_n_edges(proj);
-
-                       /* Allocate memory for all non variadic parameters in advance to be on the save side */
-                       env->cg->reg_param_req = xcalloc(get_method_n_params(tp), sizeof(ia32_register_req_t *));
-
-                       /* we are done here when there are no parameters */
-                       if (n < 1)
-                               break;
-
-                       /* temporary remember all proj arg x */
-                       projargs = xcalloc(n, sizeof(ir_node *));
-
-                       i = 0;
-                       foreach_out_edge((const ir_node *)proj, edge) {
-                               succ = get_edge_src_irn(edge);
-                               assert(is_Proj(succ) && "non-Proj from a Proj_T (pn_Start_T_args).");
-                               projargs[i++] = succ;
-                       }
-
-                       cc = get_method_calling_convention(tp);
-
-                       /* loop over all parameters and check whether its a int or float */
-                       for (i = 0; i < n; i++) {
-                               mode   = get_irn_mode(projargs[i]);
-                               cur_pn = get_Proj_proj(projargs[i]);
-
-                               if (cc & cc_reg_param) {
-                                       temp_req = ia32_get_RegParam_req(n, projargs, cur_pn, cc);
-                               }
-                               else {
-                                       temp_req = NULL;
-                               }
-
-                               if (temp_req) {
-                                       /* passed in register */
-                                       env->cg->reg_param_req[cur_pn] = temp_req;
-                               }
-                               else {
-                                       /* passed on stack */
-                                       if (mode_is_float(mode))
-                                               irn = new_rd_ia32_fStackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode);
-                                       else
-                                               irn = new_rd_ia32_StackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode);
-
-                                       set_ia32_pncode(irn, cur_pn);
-
-                                       /* kill the old "Proj Arg" and replace with the new stack param */
-                                       exchange(projargs[i], irn);
-                               }
-                       }
-
-                       free(projargs);
-
-                       break;
-               case pn_Start_P_frame_base:
-               case pn_Start_X_initial_exec:
-               case pn_Start_M:
-               case pn_Start_P_globals:
-               case pn_Start_P_value_arg_base:
-                       break;
-               default:
-                       assert(0 && "unsupported Proj(Start)");
+static ir_node *gen_CopyB(ia32_transform_env_t *env) {
+       ir_node  *res   = NULL;
+       dbg_info *dbg   = env->dbg;
+       ir_graph *irg   = env->irg;
+       ir_mode  *mode  = env->mode;
+       ir_node  *block = env->block;
+       ir_node  *node  = env->irn;
+       ir_node  *src   = get_CopyB_src(node);
+       ir_node  *dst   = get_CopyB_dst(node);
+       ir_node  *mem   = get_CopyB_mem(node);
+       ir_node  *noreg = ia32_new_NoReg_gp(env->cg);
+       int       size  = get_type_size_bytes(get_CopyB_type(node));
+       int       rem;
+
+       /* If we have to copy more than 16 bytes, we use REP MOVSx and */
+       /* then we need the size explicitly in ECX.                    */
+       if (size >= 16 * 4) {
+               rem = size & 0x3; /* size % 4 */
+               size >>= 2;
+
+               res = new_rd_ia32_Const(dbg, irg, block, mode_Is);
+               set_ia32_op_type(res, ia32_Const);
+               set_ia32_Immop_tarval(res, new_tarval_from_long(size, mode_Is));
+
+               res = new_rd_ia32_CopyB(dbg, irg, block, dst, src, res, mem, mode);
+               set_ia32_Immop_tarval(res, new_tarval_from_long(rem, mode_Is));
+       }
+       else {
+               res = new_rd_ia32_CopyB_i(dbg, irg, block, dst, src, mem, mode);
+               set_ia32_Immop_tarval(res, new_tarval_from_long(size, mode_Is));
        }
 
-       return NULL;
-#endif
+       return res;
 }
 
+
+
 /**
- * Transform some Proj's (Proj_Proj, Proj_Start, Proj_Cmp, Proj_Cond, Proj_Call).
- * All others are ignored.
+ * Transforms a Mux node into CMov.
  *
- * @param mod     the debug module
- * @param block   the block the new node should belong to
- * @param node    the ir Proj node
- * @param mode    mode of the Proj
+ * @param env   The transformation environment
  * @return The transformed node.
  */
-static ir_node *gen_Proj(ia32_transform_env_t *env) {
-       ir_node *new_node  = NULL;
-       ir_node *pred      = get_Proj_pred(env->irn);
+static ir_node *gen_Mux(ia32_transform_env_t *env) {
+       ir_node *node  = env->irn;
 
-       if (env->mode == mode_M)
-               return NULL;
+       return new_rd_ia32_CMov(env->dbg, env->irg, env->block,
+               get_Mux_sel(node), get_Mux_false(node), get_Mux_true(node), env->mode);
+}
 
-       if (get_irn_op(pred) == op_Start) {
-               new_node = gen_Proj_Start(env, env->irn, pred);
-       }
 
-       return new_node;
+
+/********************************************
+ *  _                          _
+ * | |                        | |
+ * | |__   ___ _ __   ___   __| | ___  ___
+ * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
+ * | |_) |  __/ | | | (_) | (_| |  __/\__ \
+ * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
+ *
+ ********************************************/
+
+static ir_node *gen_FrameAddr(ia32_transform_env_t *env) {
+       ir_node *new_op = NULL;
+       ir_node *node   = env->irn;
+       ir_node *op     = get_irn_n(node, 0);
+       ir_node *noreg  = ia32_new_NoReg_gp(env->cg);
+       ir_node *nomem  = new_rd_NoMem(env->irg);
+
+       new_op = new_rd_ia32_Add(env->dbg, env->irg, env->block, noreg, noreg, op, noreg, nomem, mode_T);
+       set_ia32_frame_ent(new_op, be_get_frame_entity(node));
+       set_ia32_am_support(new_op, ia32_am_Full);
+       set_ia32_use_frame(new_op);
+
+       return new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, 0);
+}
+
+static ir_node *gen_FrameLoad(ia32_transform_env_t *env) {
+       ir_node *new_op = NULL;
+
+       return new_op;
+}
+
+static ir_node *gen_FrameStore(ia32_transform_env_t *env) {
+       ir_node *new_op = NULL;
+
+       return new_op;
 }
 
 
@@ -1461,8 +1343,6 @@ static ir_node *gen_Proj(ia32_transform_env_t *env) {
  *
  *********************************************************/
 
-
-
 /**
  * Transforms the given firm node (and maybe some other related nodes)
  * into one or more assembler nodes.
@@ -1479,7 +1359,6 @@ void ia32_transform_node(ir_node *node, void *env) {
        if (is_Block(node))
                return;
 
-       tenv.arch_env = cgenv->arch_env;
        tenv.block    = get_nodes_block(node);
        tenv.dbg      = get_irn_dbg_info(node);
        tenv.irg      = current_ir_graph;
@@ -1493,6 +1372,16 @@ void ia32_transform_node(ir_node *node, void *env) {
 #define GEN(a)   case iro_##a: asm_node = gen_##a(&tenv); break
 #define IGN(a)   case iro_##a: break
 #define BAD(a)   case iro_##a: goto bad
+#define OTHER_BIN(a)                                                       \
+       if (get_irn_op(node) == get_op_##a()) {                                \
+               asm_node = gen_##a(&tenv, get_irn_n(node, 0), get_irn_n(node, 1)); \
+               break;                                                             \
+       }
+#define BE_GEN(a)                  \
+       if (be_is_##a(node)) {         \
+               asm_node = gen_##a(&tenv); \
+               break;                     \
+       }
 
        DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
 
@@ -1523,10 +1412,13 @@ void ia32_transform_node(ir_node *node, void *env) {
                GEN(Store);
                GEN(Cond);
 
-               IGN(Proj);
+               GEN(CopyB);
+               GEN(Mux);
+
                IGN(Call);
                IGN(Alloc);
 
+               IGN(Proj);
                IGN(Block);
                IGN(Start);
                IGN(End);
@@ -1536,16 +1428,17 @@ void ia32_transform_node(ir_node *node, void *env) {
                IGN(Break);
                IGN(Cmp);
                IGN(Unknown);
+
                /* constant transformation happens earlier */
                IGN(Const);
                IGN(SymConst);
+               IGN(Sync);
 
                BAD(Raise);
                BAD(Sel);
                BAD(InstOf);
                BAD(Cast);
                BAD(Free);
-               BAD(Sync);
                BAD(Tuple);
                BAD(Id);
                BAD(Bad);
@@ -1554,25 +1447,22 @@ void ia32_transform_node(ir_node *node, void *env) {
                BAD(CallBegin);
                BAD(EndReg);
                BAD(EndExcept);
-               BAD(Mux);
-               BAD(CopyB);
 
                default:
-                       if (get_irn_op(node) == get_op_Max()) {
-                               asm_node = gen_Max(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
-                       }
-                       else if (get_irn_op(node) == get_op_Min()) {
-                               asm_node = gen_Min(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
-                       }
-                       else if (get_irn_op(node) == get_op_Mulh()) {
-                               asm_node = gen_Mulh(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
-                       }
+                       OTHER_BIN(Max);
+                       OTHER_BIN(Min);
+                       OTHER_BIN(Mulh);
+
+                       BE_GEN(FrameAddr);
+                       BE_GEN(FrameLoad);
+                       BE_GEN(FrameStore);
                        break;
 bad:
                fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
                assert(0);
        }
 
+       /* exchange nodes if a new one was generated */
        if (asm_node) {
                exchange(node, asm_node);
                DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
@@ -1580,4 +1470,12 @@ bad:
        else {
                DB((tenv.mod, LEVEL_1, "ignored\n"));
        }
+
+#undef UNOP
+#undef BINOP
+#undef GEN
+#undef IGN
+#undef BAD
+#undef OTHER_BIN
+#undef BE_GEN
 }