code refactoring for full addressmode support and more architecture independence
authorChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Mon, 20 Feb 2006 14:25:16 +0000 (14:25 +0000)
committerChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Mon, 20 Feb 2006 14:25:16 +0000 (14:25 +0000)
ir/be/ia32/bearch_ia32.c
ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_emitter.h
ir/be/ia32/ia32_map_regs.c
ir/be/ia32/ia32_new_nodes.c
ir/be/ia32/ia32_new_nodes.h
ir/be/ia32/ia32_nodes_attr.h
ir/be/ia32/ia32_spec.pl
ir/be/ia32/ia32_transform.c

index ac7f6b3..40cfacf 100644 (file)
@@ -41,6 +41,8 @@ static set *cur_reg_set = NULL;
 #undef is_Start
 #define is_Start(irn) (get_irn_opcode(irn) == iro_Start)
 
+extern ir_node *be_new_NoReg(ir_graph *irg);
+
 /**************************************************
  *                         _ _              _  __
  *                        | | |            (_)/ _|
@@ -133,6 +135,7 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_re
                assert(irn_req && "missing requirement for regparam");
                memcpy(req, &(irn_req->req), sizeof(*req));
                return req;
+               //return NULL;
        }
        else if (is_Proj(irn)) {
                if (pos == -1) {
@@ -170,9 +173,9 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_re
                if (is_Phi(irn)) {
                        DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
                        if (mode_is_float(mode))
-                               memcpy(req, &(ia32_default_req_ia32_floating_point.req), sizeof(*req));
+                               memcpy(req, &(ia32_default_req_ia32_fp.req), sizeof(*req));
                        else if (mode_is_int(mode) || mode_is_reference(mode))
-                               memcpy(req, &(ia32_default_req_ia32_general_purpose.req), sizeof(*req));
+                               memcpy(req, &(ia32_default_req_ia32_gp.req), sizeof(*req));
                        else if (mode == mode_T || mode == mode_M) {
                                DBG((mod, LEVEL_1, "ignoring Phi node %+F\n", irn));
                                return NULL;
@@ -195,7 +198,7 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_re
                }
                else if (get_irn_op(irn) == op_Return && pos > 0) {
                        DB((mod, LEVEL_1, "returning reqs EAX for %+F\n", irn));
-                       memcpy(req, &(ia32_default_req_ia32_general_purpose_eax.req), sizeof(*req));
+                       memcpy(req, &(ia32_default_req_ia32_gp_eax.req), sizeof(*req));
                }
                else {
                        DB((mod, LEVEL_1, "returning NULL for %+F (not ia32)\n", irn));
@@ -275,7 +278,7 @@ static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
        if (is_ia32_irn(irn))
                return get_ia32_flags(irn);
        else {
-               if (is_Start_Proj(irn) || is_Unknown(irn))
+               if (is_Start_Proj(irn))
                        return arch_irn_flags_ignore;
 
                return 0;
@@ -337,7 +340,7 @@ static void ia32_prepare_graph(void *self) {
                irg_walk_blkwise_graph(cg->irg, check_for_alloca, NULL, &(cg->has_alloca));
 
                if (cg->has_alloca) {
-                       ia32_general_purpose_regs[REG_EBP].type = arch_register_type_ignore;
+                       ia32_gp_regs[REG_EBP].type = arch_register_type_ignore;
                }
 
                irg_walk_blkwise_graph(cg->irg, ia32_place_consts, ia32_transform_node, cg);
@@ -350,6 +353,7 @@ static void ia32_prepare_graph(void *self) {
  * Stack reservation and StackParam lowering.
  */
 static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
+#if 0
        firm_dbg_module_t *mod       = cg->mod;
        ir_node           *frame     = get_irg_frame(irg);
        ir_node           *end_block = get_irg_end_block(irg);
@@ -363,10 +367,10 @@ static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
 
        /* Determine stack register */
        if (cg->has_alloca) {
-               stack_reg = &ia32_general_purpose_regs[REG_EBP];
+               stack_reg = &ia32_gp_regs[REG_EBP];
        }
        else {
-               stack_reg = &ia32_general_purpose_regs[REG_ESP];
+               stack_reg = &ia32_gp_regs[REG_ESP];
        }
 
        /* If frame is used, then we need to reserve some stackspace. */
@@ -443,6 +447,7 @@ static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
                        sched_add_after(sched_point, stack_free);
                }
        }
+#endif
 }
 
 
@@ -470,15 +475,18 @@ static ir_node *ia32_lower_spill(void *self, ir_node *spill) {
        ir_node         *ptr   = get_irg_frame(cg->irg);
        ir_node         *val   = be_get_Spill_context(spill);
        ir_node         *mem   = new_rd_NoMem(cg->irg);
+       ir_node         *noreg = be_new_NoReg(cg->irg);
        ir_mode         *mode  = get_irn_mode(spill);
        ir_node         *res;
        entity          *ent   = be_get_spill_entity(spill);
        unsigned         offs  = get_entity_offset_bytes(ent);
+       char             buf[64];
 
        DB((cg->mod, LEVEL_1, "lower_spill: got offset %d for %+F\n", offs, ent));
 
-       res = new_rd_ia32_Store(dbg, cg->irg, block, ptr, val, mem, mode);
-       set_ia32_am_offs(res, new_tarval_from_long(offs, mode_Iu));
+       res = new_rd_ia32_Store(dbg, cg->irg, block, ptr, noreg, val, mem, mode);
+       snprintf(buf, sizeof(buf), "%d", offs);
+       add_ia32_am_offs(res, buf);
 
        return res;
 }
@@ -493,24 +501,29 @@ static ir_node *ia32_lower_reload(void *self, ir_node *reload) {
        ir_node         *ptr   = get_irg_frame(cg->irg);
        ir_mode         *mode  = get_irn_mode(reload);
        ir_node         *pred  = get_irn_n(reload, 0);
-       tarval          *tv;
+       ir_node         *noreg = be_new_NoReg(cg->irg);
+       char             buf[64];
+       char            *ofs;
        ir_node         *res;
 
        if (be_is_Spill(pred)) {
                entity   *ent  = be_get_spill_entity(pred);
                unsigned  offs = get_entity_offset_bytes(ent);
                DB((cg->mod, LEVEL_1, "lower_reload: got offset %d for %+F\n", offs, ent));
-               tv = new_tarval_from_long(offs, mode_Iu);
+
+               snprintf(buf, sizeof(buf), "%d", offs);
        }
        else if (is_ia32_Store(pred)) {
-               tv = get_ia32_am_offs(pred);
+               ofs = get_ia32_am_offs(pred);
+               strncpy(buf, ofs, sizeof(buf));
+               free(ofs);
        }
        else {
                assert(0 && "unsupported Reload predecessor");
        }
 
-       res = new_rd_ia32_Load(dbg, cg->irg, block, ptr, pred, mode);
-       set_ia32_am_offs(res, tv);
+       res = new_rd_ia32_Load(dbg, cg->irg, block, ptr, noreg, pred, mode);
+       add_ia32_am_offs(res, buf);
 
        return res;
 }
@@ -522,10 +535,10 @@ static const arch_register_t *ia32_get_stack_register(void *self) {
        ia32_code_gen_t *cg = self;
 
        if (cg->has_alloca) {
-               return &ia32_general_purpose_regs[REG_EBP];
+               return &ia32_gp_regs[REG_EBP];
        }
 
-       return &ia32_general_purpose_regs[REG_ESP];
+       return &ia32_gp_regs[REG_ESP];
 }
 
 /**
@@ -543,7 +556,7 @@ static void ia32_codegen(void *self) {
        }
 
        ia32_finish_irg(irg, cg);
-       dump_ir_block_graph_sched(irg, "-finished");
+       //dump_ir_block_graph_sched(irg, "-finished");
        ia32_gen_routine(out, irg, cg);
 
        cur_reg_set = NULL;
@@ -674,17 +687,17 @@ long ia32_handle_call_proj(const void *self, ir_node *proj, int is_keep) {
                        assert(pn == 0 && "only one floating point result supported");
 
                        /* Get the proj number for the floating point result */
-                       pn = ia32_get_reg_projnum(&ia32_floating_point_regs[REG_XMM0], isa->reg_projnum_map);
+                       pn = ia32_get_reg_projnum(&ia32_fp_regs[REG_XMM0], isa->reg_projnum_map);
                }
                else {
                        /* In case of 64bit return value, the result is */
                        /* in EDX:EAX and we have two result projs.     */
                        switch (pn) {
                                case 0:
-                                       pn = ia32_get_reg_projnum(&ia32_general_purpose_regs[REG_EAX], isa->reg_projnum_map);
+                                       pn = ia32_get_reg_projnum(&ia32_gp_regs[REG_EAX], isa->reg_projnum_map);
                                        break;
                                case 1:
-                                       pn = ia32_get_reg_projnum(&ia32_general_purpose_regs[REG_EDX], isa->reg_projnum_map);
+                                       pn = ia32_get_reg_projnum(&ia32_gp_regs[REG_EDX], isa->reg_projnum_map);
                                        break;
                                default:
                                        assert(0 && "only two int results supported");
@@ -696,7 +709,7 @@ long ia32_handle_call_proj(const void *self, ir_node *proj, int is_keep) {
        }
        else {
                /* Set mode to floating point if required */
-               if (!strcmp(ia32_reg_classes[CLASS_ia32_floating_point].name,
+               if (!strcmp(ia32_reg_classes[CLASS_ia32_fp].name,
                                        ia32_projnum_reg_req_map[pn]->req.cls->name)) {
                        set_irn_mode(proj, mode_F);
                }
@@ -722,7 +735,7 @@ list_sched_selector_t ia32_sched_selector;
  * Returns the reg_pressure scheduler with to_appear_in_schedule() overloaded
  */
 static const list_sched_selector_t *ia32_get_list_sched_selector(const void *self) {
-       memcpy(&ia32_sched_selector, reg_pressure_selector, sizeof(list_sched_selector_t));
+       memcpy(&ia32_sched_selector, trivial_selector, sizeof(list_sched_selector_t));
        ia32_sched_selector.to_appear_in_schedule = ia32_to_appear_in_schedule;
        return &ia32_sched_selector;
 }
index caf4f18..03907b4 100644 (file)
 
 static const arch_env_t *arch_env = NULL;
 
+char *ia32_emit_binop(ir_node *irn) {
+       return "R1, R2";
+}
+
+char *ia32_emit_unop(ir_node *irn) {
+       return "R";
+}
+
+char *ia32_emit_am(ir_node *irn) {
+       return "AM";
+}
 
 /*************************************************************
  *             _       _    __   _          _
@@ -41,35 +52,24 @@ static const arch_env_t *arch_env = NULL;
  * Return node's tarval as string.
  */
 const char *node_const_to_str(ir_node *n) {
-       char   *buf;
-       tarval *tv = get_ia32_Immop_tarval(n);
+       char *s = get_ia32_cnst(n);
 
-       if (tv) {
-               buf = xmalloc(SNPRINTF_BUF_LEN);
-               tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv);
-               return buf;
-       }
-       else if (get_ia32_old_ir(n)) {
-               return get_sc_name(get_ia32_old_ir(n));
-       }
-       else
-               return "0";
+       if (!s)
+               s = "NULL";
+
+       return s;
 }
 
 /**
  * Returns node's offset as string.
  */
 char *node_offset_to_str(ir_node *n) {
-       char   *buf;
-       tarval *tv = get_ia32_am_offs(n);
+       char *s = get_ia32_am_offs(n);
 
-       if (tv) {
-               buf = xmalloc(SNPRINTF_BUF_LEN);
-               tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv);
-               return buf;
-       }
-       else
-               return "";
+       if (!s)
+               s = "";
+
+       return s;
 }
 
 /* We always pass the ir_node which is a pointer. */
@@ -736,15 +736,10 @@ void ia32_emit_node(ir_node *irn, void *env) {
 #define EMIT(a)      if (get_irn_opcode(irn) == iro_##a) { emit_##a(irn, emit_env); return; }
 
        /* generated int emitter functions */
-       IA32_EMIT(Copy);
-       IA32_EMIT(Perm);
-
        IA32_EMIT(Const);
 
        IA32_EMIT(Add);
-       IA32_EMIT(Add_i);
        IA32_EMIT(Sub);
-       IA32_EMIT(Sub_i);
        IA32_EMIT(Minus);
        IA32_EMIT(Inc);
        IA32_EMIT(Dec);
@@ -753,30 +748,21 @@ void ia32_emit_node(ir_node *irn, void *env) {
        IA32_EMIT(Min);
 
        IA32_EMIT(And);
-       IA32_EMIT(And_i);
        IA32_EMIT(Or);
-       IA32_EMIT(Or_i);
        IA32_EMIT(Eor);
-       IA32_EMIT(Eor_i);
        IA32_EMIT(Not);
 
        IA32_EMIT(Shl);
-       IA32_EMIT(Shl_i);
        IA32_EMIT(Shr);
-       IA32_EMIT(Shr_i);
        IA32_EMIT(Shrs);
-       IA32_EMIT(Shrs_i);
        IA32_EMIT(RotL);
-       IA32_EMIT(RotL_i);
        IA32_EMIT(RotR);
 
        IA32_EMIT(Lea);
-       IA32_EMIT(Lea_i);
 
        IA32_EMIT(Mul);
-       IA32_EMIT(Mul_i);
 
-       IA32_EMIT(Cltd);
+       IA32_EMIT(Cdq);
        IA32_EMIT(DivMod);
 
        IA32_EMIT(Store);
@@ -787,7 +773,6 @@ void ia32_emit_node(ir_node *irn, void *env) {
 
        IA32_EMIT(fAdd);
        IA32_EMIT(fSub);
-       IA32_EMIT(fMinus);
 
        IA32_EMIT(fMul);
        IA32_EMIT(fDiv);
@@ -800,11 +785,8 @@ void ia32_emit_node(ir_node *irn, void *env) {
 
        /* other emitter functions */
        IA32_EMIT(CondJmp);
-       IA32_EMIT(CondJmp_i);
        IA32_EMIT(SwitchJmp);
        IA32_EMIT(Call);
-       IA32_EMIT(Alloca);
-       IA32_EMIT(Alloca_i);
 
        EMIT(Jmp);
        EMIT(Proj);
index 584b864..3f52919 100644 (file)
@@ -18,7 +18,9 @@ typedef struct _emit_env_t {
 
 const lc_arg_env_t *ia32_get_arg_env(void);
 
-void equalize_dest_src(FILE *F, ir_node *n);
+char *ia32_emit_binop(ir_node *irn);
+char *ia32_emit_unop(ir_node *irn);
+char *ia32_emit_am(ir_node *irn);
 
 int get_ia32_reg_nr(ir_node *irn, int posi, int in_out);
 const char *get_ia32_in_reg_name(ir_node *irn, int pos);
index 1173ced..745f7ab 100644 (file)
@@ -18,44 +18,44 @@ static int maxnum_fpreg_args = 5;   /* maximum number of float arguments passed
 /* this is the order of the assigned registers usesd for parameter passing */
 
 const ia32_register_req_t *gpreg_param_req_std[] = {
-       &ia32_default_req_ia32_general_purpose_eax,
-       &ia32_default_req_ia32_general_purpose_ecx,
-       &ia32_default_req_ia32_general_purpose_edx,
-       &ia32_default_req_ia32_general_purpose_ebx,
-       &ia32_default_req_ia32_general_purpose_edi,
-       &ia32_default_req_ia32_general_purpose_esi
+       &ia32_default_req_ia32_gp_eax,
+       &ia32_default_req_ia32_gp_ecx,
+       &ia32_default_req_ia32_gp_edx,
+       &ia32_default_req_ia32_gp_ebx,
+       &ia32_default_req_ia32_gp_edi,
+       &ia32_default_req_ia32_gp_esi
 };
 
 const ia32_register_req_t *gpreg_param_req_this[] = {
-       &ia32_default_req_ia32_general_purpose_ecx,
-       &ia32_default_req_ia32_general_purpose_eax,
-       &ia32_default_req_ia32_general_purpose_edx,
-       &ia32_default_req_ia32_general_purpose_ebx,
-       &ia32_default_req_ia32_general_purpose_edi,
-       &ia32_default_req_ia32_general_purpose_esi
+       &ia32_default_req_ia32_gp_ecx,
+       &ia32_default_req_ia32_gp_eax,
+       &ia32_default_req_ia32_gp_edx,
+       &ia32_default_req_ia32_gp_ebx,
+       &ia32_default_req_ia32_gp_edi,
+       &ia32_default_req_ia32_gp_esi
 };
 
 const ia32_register_req_t *fpreg_param_req_std[] = {
-       &ia32_default_req_ia32_floating_point_xmm0,
-       &ia32_default_req_ia32_floating_point_xmm1,
-       &ia32_default_req_ia32_floating_point_xmm2,
-       &ia32_default_req_ia32_floating_point_xmm3,
-       &ia32_default_req_ia32_floating_point_xmm4,
-       &ia32_default_req_ia32_floating_point_xmm5,
-       &ia32_default_req_ia32_floating_point_xmm6,
-       &ia32_default_req_ia32_floating_point_xmm7
+       &ia32_default_req_ia32_fp_xmm0,
+       &ia32_default_req_ia32_fp_xmm1,
+       &ia32_default_req_ia32_fp_xmm2,
+       &ia32_default_req_ia32_fp_xmm3,
+       &ia32_default_req_ia32_fp_xmm4,
+       &ia32_default_req_ia32_fp_xmm5,
+       &ia32_default_req_ia32_fp_xmm6,
+       &ia32_default_req_ia32_fp_xmm7
 };
 
 const ia32_register_req_t *fpreg_param_req_this[] = {
        NULL,  /* in case of a "this" pointer, the first parameter must not be a float */
-       &ia32_default_req_ia32_floating_point_xmm0,
-       &ia32_default_req_ia32_floating_point_xmm1,
-       &ia32_default_req_ia32_floating_point_xmm2,
-       &ia32_default_req_ia32_floating_point_xmm3,
-       &ia32_default_req_ia32_floating_point_xmm4,
-       &ia32_default_req_ia32_floating_point_xmm5,
-       &ia32_default_req_ia32_floating_point_xmm6,
-       &ia32_default_req_ia32_floating_point_xmm7
+       &ia32_default_req_ia32_fp_xmm0,
+       &ia32_default_req_ia32_fp_xmm1,
+       &ia32_default_req_ia32_fp_xmm2,
+       &ia32_default_req_ia32_fp_xmm3,
+       &ia32_default_req_ia32_fp_xmm4,
+       &ia32_default_req_ia32_fp_xmm5,
+       &ia32_default_req_ia32_fp_xmm6,
+       &ia32_default_req_ia32_fp_xmm7
 };
 
 
@@ -247,13 +247,13 @@ long ia32_translate_proj_pos(const ir_node *proj) {
        else if (is_ia32_Store(pred)) {
                return 0;
        }
-       else if (is_ia32_CondJmp(pred) || is_ia32_CondJmp_i(pred)) {
+       else if (is_ia32_CondJmp(pred)) {
                return 0;
        }
        else if (is_ia32_SwitchJmp(pred)) {
                return 0;
        }
-       else if (is_ia32_Cltd(pred) || is_ia32_Mul(pred)) {
+       else if (is_ia32_Cdq(pred) || is_ia32_Mulh(pred)) {
                if (nr == pn_EAX)
                        return 0;
                if (nr == pn_EDX)
@@ -265,6 +265,12 @@ long ia32_translate_proj_pos(const ir_node *proj) {
                if (nr == pn_DivMod_res_mod || pn_Mod_res)
                        return 1;
        }
+       else if (is_ia32_fDiv(pred)) {
+               if (nr == pn_Quot_res)
+                       return 0;
+               else
+                       assert(0 && "there should be no more Projs for a fDiv");
+       }
        else if (is_ia32_Call(pred)) {
                return 0;
        }
index fe05c63..1182017 100644 (file)
@@ -9,6 +9,12 @@
 #include "config.h"
 #endif
 
+#ifdef _WIN32
+#include <malloc.h>
+#else
+#include <alloc.h>
+#endif
+
 #include <stdlib.h>
 
 #include "irprog_t.h"
@@ -20,6 +26,7 @@
 #include "irop.h"
 #include "firm_common_t.h"
 #include "irvrfy_t.h"
+#include "irprintf.h"
 
 #include "../bearch.h"
 
 #include "ia32_new_nodes.h"
 #include "gen_ia32_regalloc_if.h"
 
-
+#ifdef obstack_chunk_alloc
+# undef obstack_chunk_alloc
+# define obstack_chunk_alloc xmalloc
+#else
+# define obstack_chunk_alloc xmalloc
+# define obstack_chunk_free free
+#endif
 
 /***********************************************************************************
  *      _                                   _       _             __
@@ -79,6 +92,81 @@ const char *get_sc_name(ir_node *symc) {
        return NULL;
 }
 
+/**
+ * Returns a string containing the names of all registers within the limited bitset
+ */
+static char *get_limited_regs(const arch_register_req_t *req, char *buf, int max) {
+       bitset_t *bs   = bitset_alloca(req->cls->n_regs);
+       char     *p    = buf;
+       int       size = 0;
+       int       i, cnt;
+
+       req->limited(NULL, bs);
+
+       for (i = 0; i < req->cls->n_regs; i++) {
+               if (bitset_is_set(bs, i)) {
+                       cnt = snprintf(p, max - size, " %s", req->cls->regs[i].name);
+                       if (cnt < 0) {
+                               fprintf(stderr, "dumper problem, exiting\n");
+                               exit(1);
+                       }
+
+                       p    += cnt;
+                       size += cnt;
+
+                       if (size >= max)
+                               break;
+               }
+       }
+
+       return buf;
+}
+
+/**
+ * Dumps the register requirements for either in or out.
+ */
+static void dump_reg_req(FILE *F, ir_node *n, const ia32_register_req_t **reqs, int inout) {
+       char *dir = inout ? "out" : "in";
+       int   max = inout ? get_ia32_n_res(n) : get_irn_arity(n);
+       char *buf = alloca(1024);
+       int   i;
+
+       memset(buf, 0, 1024);
+
+       if (reqs) {
+               for (i = 0; i < max; i++) {
+                       fprintf(F, "%sreq #%d =", dir, i);
+
+                       if (reqs[i]->req.type == arch_register_req_type_none) {
+                               fprintf(F, " n/a");
+                       }
+
+                       if (reqs[i]->req.type & arch_register_req_type_normal) {
+                               fprintf(F, " %s", reqs[i]->req.cls->name);
+                       }
+
+                       if (reqs[i]->req.type & arch_register_req_type_limited) {
+                               fprintf(F, " %s", get_limited_regs(&reqs[i]->req, buf, 1024));
+                       }
+
+                       if (reqs[i]->req.type & arch_register_req_type_should_be_same) {
+                               ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->pos));
+                       }
+
+                       if (reqs[i]->req.type & arch_register_req_type_should_be_different) {
+                               ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->pos));
+                       }
+
+                       fprintf(F, "\n");
+               }
+
+               fprintf(F, "\n");
+       }
+       else {
+               fprintf(F, "%sreq = N/A\n", dir);
+       }
+}
+
 /**
  * Dumper interface for dumping ia32 nodes in vcg.
  * @param n        the node to dump
@@ -87,18 +175,16 @@ const char *get_sc_name(ir_node *symc) {
  * @return 0 on success or != 0 on failure
  */
 static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
-       const char *name, *p;
-       ir_mode    *mode = NULL;
-       int        bad   = 0;
-       asmop_attr *attr;
-       int        i;
+       ir_mode     *mode = NULL;
+       int          bad  = 0;
+       int          i;
+       ia32_attr_t *attr;
        const ia32_register_req_t **reqs;
        const arch_register_t     **slots;
 
        switch (reason) {
                case dump_node_opcode_txt:
-                       name = get_irn_opname(n);
-                       fprintf(F, "%s", name);
+                       fprintf(F, "%s", get_irn_opname(n));
                        break;
 
                case dump_node_mode_txt:
@@ -108,7 +194,7 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
                                mode = NULL;
                        }
                        else if (is_ia32_Load(n)) {
-                               mode = get_irn_mode(get_irn_n(n, 1));
+                               mode = get_irn_mode(get_irn_n(n, 0));
                        }
                        else if (is_ia32_Store(n)) {
                                mode = get_irn_mode(get_irn_n(n, 2));
@@ -120,70 +206,39 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
                        break;
 
                case dump_node_nodeattr_txt:
-                       name = get_irn_opname(n);
-                       p = name + strlen(name) - 2;
-                       if ((p[0] == '_' && p[1] == 'i') || is_ia32_Const(n) || is_ia32_fConst(n)) {
-                               tarval *tv = get_ia32_Immop_tarval(n);
-                               if (tv) {
-                                       fprintf_tv(F, tv, 1);
-                               }
-                               else {
-                                       fprintf(F, "[SymC &%s]", get_sc_name(get_ia32_old_ir(n)));
-                               }
+                       if (is_ia32_Call(n)) {
+                               fprintf(F, "&%s ", get_ia32_sc(n));
                        }
-                       else if (is_ia32_Call(n)) {
-                               ir_node *sc = get_ia32_old_ir(n);
+                       else if (get_ia32_cnst(n)) {
+                               char *pref = "";
 
-                               fprintf(F, "&%s ", get_sc_name(sc));
+                               if (get_ia32_sc(n)) {
+                                       pref = "SymC ";
+                               }
+
+                               fprintf(F, "[%s%s]", pref, get_ia32_cnst(n));
                        }
 
-                       if (is_ia32_AddrMode(n)) {
-                               fprintf(F, "[AddrMode] ");
+                       if (is_ia32_AddrModeS(n) || is_ia32_AddrModeD(n)) {
+                               fprintf(F, "[AM] ");
                        }
 
                        break;
 
                case dump_node_info_txt:
                        attr = get_ia32_attr(n);
+                       fprintf(F, "=== IA32 attr begin ===\n");
 
                        /* dump IN requirements */
                        if (get_irn_arity(n) > 0) {
                                reqs = get_ia32_in_req_all(n);
-
-                               if (reqs) {
-                                       for (i = 0; i < get_irn_arity(n); i++) {
-                                               if (reqs[i]->req.type != arch_register_req_type_none) {
-                                                       fprintf(F, "inreq[%d]=[%s]\n", i, reqs[i]->req.cls->name);
-                                               }
-                                               else {
-                                                       fprintf(F, "inreq[%d]=[none]\n", i);
-                                               }
-                                       }
-
-                                       fprintf(F, "\n");
-                               }
-                               else {
-                                       fprintf(F, "NO IN REQS\n");
-                               }
+                               dump_reg_req(F, n, reqs, 0);
                        }
 
                        /* dump OUT requirements */
                        if (attr->n_res > 0) {
                                reqs = get_ia32_out_req_all(n);
-
-                               if (reqs) {
-                                       for (i = 0; i < attr->n_res; i++) {
-                                               if (reqs[i]->req.type != arch_register_req_type_none) {
-                                                       fprintf(F, "outreq[%d]=[%s]\n", i, reqs[i]->req.cls->name);
-                                               }
-                                               else {
-                                                       fprintf(F, "outreq[%d]=[none]\n", i);
-                                               }
-                                       }
-                               }
-                               else {
-                                       fprintf(F, "NO OUT REQS\n");
-                               }
+                               dump_reg_req(F, n, reqs, 1);
                        }
 
                        /* dump assigned registers */
@@ -198,29 +253,82 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
                                        }
                                }
                        }
+                       fprintf(F, "\n");
+
+                       /* dump op type */
+                       fprintf(F, "op = ");
+                       switch (attr->tp) {
+                               case ia32_Normal:
+                                       fprintf(F, "Normal");
+                                       break;
+                               case ia32_Const:
+                                       fprintf(F, "Const");
+                                       break;
+                               case ia32_SymConst:
+                                       fprintf(F, "SymConst");
+                                       break;
+                               case ia32_AddrModeD:
+                                       fprintf(F, "AM Dest (Load+Store)");
+                                       break;
+                               case ia32_AddrModeS:
+                                       fprintf(F, "AM Source (Load)");
+                                       break;
+                       }
+                       fprintf(F, "\n");
+
+
+                       /* dump supported am */
+                       fprintf(F, "AM support = ");
+                       switch (attr->am_support) {
+                               case ia32_am_None:
+                                       fprintf(F, "none");
+                                       break;
+                               case ia32_am_Source:
+                                       fprintf(F, "source only (Load)");
+                                       break;
+                               case ia32_am_Dest:
+                                       fprintf(F, "dest only (Load+Store)");
+                                       break;
+                               case ia32_am_Full:
+                                       fprintf(F, "full");
+                                       break;
+                       }
+                       fprintf(F, "\n");
 
-                       /* special for LEA */
-                       if (is_ia32_Lea(n) || is_ia32_Lea_i(n)) {
-                               tarval *o  = get_ia32_am_offs(n);
-                               tarval *tv = get_ia32_Immop_tarval(n);
+                       /* dump AM offset */
+                       fprintf(F, "AM offset = ");
+                       if (attr->am_offs) {
+                               fprintf(F, "%s", get_ia32_am_offs(n));
+                       }
+                       else {
+                               fprintf(F, "n/a");
+                       }
+                       fprintf(F, "\n");
 
-                               fprintf(F, "LEA ");
-                               if (o) {
-                                       fprintf_tv(F, o, 0);
-                               }
+                       /* dump AM scale */
+                       fprintf(F, "AM scale = %d\n", get_ia32_am_scale(n));
 
-                               fprintf(F, "(%s", get_irn_opname(get_irn_n(n, 0)));
+                       /* dump pn code */
+                       fprintf(F, "pn_code = %d\n", get_ia32_pncode(n));
 
-                               if (is_ia32_Lea(n)) {
-                                       fprintf(F, ", %s", get_irn_opname(get_irn_n(n, 1)));
-                               }
+                       /* dump n_res */
+                       fprintf(F, "n_res = %d\n", get_ia32_n_res(n));
 
-                               if (tv) {
-                                       fprintf(F, ", ");
-                                       fprintf_tv(F, tv, 0);
-                               }
-                               fprintf(F, ")\n");
+                       /* dump flags */
+                       fprintf(F, "flags =");
+                       if (attr->flags & arch_irn_flags_dont_spill) {
+                               fprintf(F, " unspillable");
+                       }
+                       if (attr->flags & arch_irn_flags_rematerializable) {
+                               fprintf(F, " remat");
+                       }
+                       if (attr->flags & arch_irn_flags_ignore) {
+                               fprintf(F, " ignore");
                        }
+                       fprintf(F, "\n");
+
+                       fprintf(F, "=== IA32 attr end ===\n");
+                       /* end of: case dump_node_info_txt */
                        break;
        }
 
@@ -240,84 +348,136 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
  *                                       |___/
  ***************************************************************************************************/
 
+ static char *copy_str(char *dst, const char *src) {
+        dst = xcalloc(1, strlen(src) + 1);
+        strncpy(dst, src, strlen(src) + 1);
+        return dst;
+ }
+
+ static char *set_cnst_from_tv(char *cnst, tarval *tv) {
+        if (cnst) {
+                free(cnst);
+        }
+
+        cnst = xcalloc(1, 64);
+        assert(tarval_snprintf(cnst, 63, tv));
+        return cnst;
+ }
+
 /**
  * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
  * Firm was made by people hating const :-(
  */
-asmop_attr *get_ia32_attr(const ir_node *node) {
+ia32_attr_t *get_ia32_attr(const ir_node *node) {
        assert(is_ia32_irn(node) && "need ia32 node to get ia32 attributes");
-       return (asmop_attr *)get_irn_generic_attr((ir_node *)node);
+       return (ia32_attr_t *)get_irn_generic_attr((ir_node *)node);
 }
 
 /**
  * Gets the type of an ia32 node.
  */
-asmop_type_t get_ia32_op_type(const ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
+ia32_op_type_t get_ia32_op_type(const ir_node *node) {
+       ia32_attr_t *attr = get_ia32_attr(node);
        return attr->tp;
 }
 
 /**
  * Sets the type of an ia32 node.
  */
-void set_ia32_op_type(const ir_node *node, asmop_type_t tp) {
-       asmop_attr *attr = get_ia32_attr(node);
-       attr->tp         = tp;
+void set_ia32_op_type(ir_node *node, ia32_op_type_t tp) {
+       ia32_attr_t *attr = get_ia32_attr(node);
+       attr->tp          = tp;
 }
 
 /**
- * Gets the addr mode type of an ia32 node
+ * Gets the supported addrmode of an ia32 node
  */
-addrmode_type_t get_ia32_am_type(const ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
-       return attr->am_tp;
+ia32_am_type_t get_ia32_am_support(const ir_node *node) {
+       ia32_attr_t *attr = get_ia32_attr(node);
+       return attr->am_support;
 }
 
 /**
- * Sets the addr mode type of an ia32 node
+ * Sets the supported addrmode of an ia32 node
  */
-void set_ia32_am_type(const ir_node *node, addrmode_type_t am_tp) {
-       asmop_attr *attr = get_ia32_attr(node);
-       attr->am_tp      = am_tp;
+void set_ia32_am_support(ir_node *node, ia32_am_type_t am_tp) {
+       ia32_attr_t *attr = get_ia32_attr(node);
+       attr->am_support  = am_tp;
 }
 
 /**
- * Gets the addr mode offset.
+ * Joins all offsets to one string with adds.
  */
-tarval *get_ia32_am_offs(const ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
-       return attr->am_offs;
+char *get_ia32_am_offs(const ir_node *node) {
+       ia32_attr_t *attr = get_ia32_attr(node);
+       char        *res  = NULL;
+       int          size;
+
+       size = obstack_object_size(attr->am_offs);
+    if (size > 0) {
+               res = xcalloc(1, size + 1);
+               memcpy(res, obstack_base(attr->am_offs), size);
+    }
+
+       res[size] = '\0';
+       return res;
 }
 
 /**
- * Sets the offset for addr mode.
+ * Add an offset for addrmode.
  */
-void set_ia32_am_offs(ir_node *node, tarval *am_offs) {
-       asmop_attr *attr = get_ia32_attr(node);
-       attr->am_offs    = am_offs;
+static void extend_ia32_am_offs(ir_node *node, char *offset, char op) {
+       ia32_attr_t *attr = get_ia32_attr(node);
+
+       if (!attr->am_offs) {
+               /* obstack is not initialized */
+               attr->am_offs = xcalloc(1, sizeof(*(attr->am_offs)));
+               obstack_init(attr->am_offs);
+       }
+       else {
+               /* obstack is initialized -> there is already one offset */
+               /* present -> connect the offsets with an add            */
+               obstack_printf(attr->am_offs, " %c ", op);
+       }
+
+       obstack_printf(attr->am_offs, "%s", offset);
+}
+
+/**
+ * Add an offset for addrmode.
+ */
+void add_ia32_am_offs(ir_node *node, char *offset) {
+       extend_ia32_am_offs(node, offset, '+');
+}
+
+/**
+ * Sub an offset for addrmode.
+ */
+void sub_ia32_am_offs(ir_node *node, char *offset) {
+       extend_ia32_am_offs(node, offset, '-');
 }
 
 /**
  * Gets the addr mode const.
  */
-tarval *get_ia32_am_const(const ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
-       return attr->am_const;
+int get_ia32_am_scale(const ir_node *node) {
+       ia32_attr_t *attr = get_ia32_attr(node);
+       return attr->am_scale;
 }
 
 /**
- * Sets the const for addr mode.
+ * Sets the index register scale for addrmode.
  */
-void set_ia32_am_const(ir_node *node, tarval *am_const) {
-       asmop_attr *attr = get_ia32_attr(node);
-       attr->am_const   = am_const;
+void set_ia32_am_scale(ir_node *node, int scale) {
+       ia32_attr_t *attr = get_ia32_attr(node);
+       attr->am_scale    = scale;
 }
 
 /**
  * Return the tarval of an immediate operation or NULL in case of SymConst
  */
 tarval *get_ia32_Immop_tarval(const ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
     return attr->tv;
 }
 
@@ -325,31 +485,45 @@ tarval *get_ia32_Immop_tarval(const ir_node *node) {
  * Sets the attributes of an immediate operation to the specified tarval
  */
 void set_ia32_Immop_tarval(ir_node *node, tarval *tv) {
-       asmop_attr *attr = get_ia32_attr(node);
-       attr->tv = tv;
+       ia32_attr_t *attr = get_ia32_attr(node);
+       attr->tv          = tv;
+       attr->cnst        = set_cnst_from_tv(attr->cnst, attr->tv);
+}
+
+/**
+ * Return the sc attribute.
+ */
+char *get_ia32_sc(const ir_node *node) {
+  ia32_attr_t *attr = get_ia32_attr(node);
+  return attr->sc;
 }
 
 /**
- * Return the old_ir attribute.
+ * Sets the sc attribute.
  */
-ir_node *get_ia32_old_ir(const ir_node *node) {
-  asmop_attr *attr = get_ia32_attr(node);
-  return attr->old_ir;
+void set_ia32_sc(ir_node *node, char *sc) {
+  ia32_attr_t *attr = get_ia32_attr(node);
+  attr->sc          = copy_str(attr->sc, sc);
+
+  if (attr->cnst) {
+         free(attr->cnst);
+  }
+  attr->cnst = attr->sc;
 }
 
 /**
- * Sets the old_ir attribute.
+ * Gets the string representation of the internal const (tv or symconst)
  */
-void set_ia32_old_ir(ir_node *node, ir_node *old_ir) {
-  asmop_attr *attr = get_ia32_attr(node);
-  attr->old_ir = old_ir;
+char *get_ia32_cnst(ir_node *node) {
+  ia32_attr_t *attr = get_ia32_attr(node);
+  return attr->cnst;
 }
 
 /**
  * Returns the argument register requirements of an ia32 node.
  */
 const ia32_register_req_t **get_ia32_in_req_all(const ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
        return attr->in_req;
 }
 
@@ -357,7 +531,7 @@ const ia32_register_req_t **get_ia32_in_req_all(const ir_node *node) {
  * Returns the result register requirements of an ia32 node.
  */
 const ia32_register_req_t **get_ia32_out_req_all(const ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
        return attr->out_req;
 }
 
@@ -365,7 +539,7 @@ const ia32_register_req_t **get_ia32_out_req_all(const ir_node *node) {
  * Returns the argument register requirement at position pos of an ia32 node.
  */
 const ia32_register_req_t *get_ia32_in_req(const ir_node *node, int pos) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
        return attr->in_req[pos];
 }
 
@@ -373,7 +547,7 @@ const ia32_register_req_t *get_ia32_in_req(const ir_node *node, int pos) {
  * Returns the result register requirement at position pos of an ia32 node.
  */
 const ia32_register_req_t *get_ia32_out_req(const ir_node *node, int pos) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
        return attr->out_req[pos];
 }
 
@@ -381,7 +555,7 @@ const ia32_register_req_t *get_ia32_out_req(const ir_node *node, int pos) {
  * Sets the OUT register requirements at position pos.
  */
 void set_ia32_req_out(ir_node *node, const ia32_register_req_t *req, int pos) {
-       asmop_attr *attr   = get_ia32_attr(node);
+       ia32_attr_t *attr  = get_ia32_attr(node);
        attr->out_req[pos] = req;
 }
 
@@ -389,7 +563,7 @@ void set_ia32_req_out(ir_node *node, const ia32_register_req_t *req, int pos) {
  * Sets the IN register requirements at position pos.
  */
 void set_ia32_req_in(ir_node *node, const ia32_register_req_t *req, int pos) {
-       asmop_attr *attr  = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
        attr->in_req[pos] = req;
 }
 
@@ -397,7 +571,7 @@ void set_ia32_req_in(ir_node *node, const ia32_register_req_t *req, int pos) {
  * Returns the register flag of an ia32 node.
  */
 arch_irn_flags_t get_ia32_flags(const ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
        return attr->flags;
 }
 
@@ -405,15 +579,15 @@ arch_irn_flags_t get_ia32_flags(const ir_node *node) {
  * Sets the register flag of an ia32 node.
  */
 void set_ia32_flags(const ir_node *node, arch_irn_flags_t flags) {
-       asmop_attr *attr = get_ia32_attr(node);
-       attr->flags      = flags;
+       ia32_attr_t *attr = get_ia32_attr(node);
+       attr->flags       = flags;
 }
 
 /**
  * Returns the result register slots of an ia32 node.
  */
 const arch_register_t **get_ia32_slots(const ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
        return attr->slots;
 }
 
@@ -421,7 +595,7 @@ const arch_register_t **get_ia32_slots(const ir_node *node) {
  * Returns the name of the OUT register at position pos.
  */
 const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
 
        assert(is_ia32_irn(node) && "Not an ia32 node.");
        assert(pos < attr->n_res && "Invalid OUT position.");
@@ -434,7 +608,7 @@ const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
  * Returns the index of the OUT register at position pos within its register class.
  */
 int get_ia32_out_regnr(const ir_node *node, int pos) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
 
        assert(is_ia32_irn(node) && "Not an ia32 node.");
        assert(pos < attr->n_res && "Invalid OUT position.");
@@ -447,7 +621,7 @@ int get_ia32_out_regnr(const ir_node *node, int pos) {
  * Returns the OUT register at position pos.
  */
 const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
 
        assert(is_ia32_irn(node) && "Not an ia32 node.");
        assert(pos < attr->n_res && "Invalid OUT position.");
@@ -460,39 +634,39 @@ const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos) {
  * Sets the number of results.
  */
 void set_ia32_n_res(ir_node *node, int n_res) {
-       asmop_attr *attr = get_ia32_attr(node);
-       attr->n_res      = n_res;
+       ia32_attr_t *attr = get_ia32_attr(node);
+       attr->n_res       = n_res;
 }
 
 /**
  * Returns the number of results.
  */
 int get_ia32_n_res(const ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
        return attr->n_res;
 }
 
 /**
  * Returns the flavour of an ia32 node,
  */
-op_flavour_t get_ia32_flavour(const ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
+ia32_op_flavour_t get_ia32_flavour(const ir_node *node) {
+       ia32_attr_t *attr = get_ia32_attr(node);
        return attr->op_flav;
 }
 
 /**
  * Sets the flavour of an ia32 node to flavour_Div/Mod/DivMod/Mul/Mulh.
  */
-void set_ia32_flavour(ir_node *node, op_flavour_t op_flav) {
-       asmop_attr *attr = get_ia32_attr(node);
-       attr->op_flav    = op_flav;
+void set_ia32_flavour(ir_node *node, ia32_op_flavour_t op_flav) {
+       ia32_attr_t *attr = get_ia32_attr(node);
+       attr->op_flav     = op_flav;
 }
 
 /**
  * Returns the projnum code.
  */
 long get_ia32_pncode(const ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
        return attr->pn_code;
 }
 
@@ -500,8 +674,8 @@ long get_ia32_pncode(const ir_node *node) {
  * Sets the projnum code
  */
 void set_ia32_pncode(ir_node *node, long code) {
-       asmop_attr *attr = get_ia32_attr(node);
-       attr->pn_code    = code;
+       ia32_attr_t *attr = get_ia32_attr(node);
+       attr->pn_code     = code;
 }
 
 
@@ -520,7 +694,7 @@ void set_ia32_pncode(ir_node *node, long code) {
  * Gets the type of an ia32_Const.
  */
 unsigned get_ia32_Const_type(ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
 
        assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to get type");
 
@@ -531,10 +705,10 @@ unsigned get_ia32_Const_type(ir_node *node) {
  * Sets the type of an ia32_Const.
  */
 void set_ia32_Const_type(ir_node *node, int type) {
-       asmop_attr *attr = get_ia32_attr(node);
+       ia32_attr_t *attr = get_ia32_attr(node);
 
        assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to set type");
-       assert((type == asmop_Const || type == asmop_SymConst) && "Unsupported ia32_Const type");
+       assert((type == ia32_Const || type == ia32_SymConst) && "Unsupported ia32_Const type");
 
        attr->tp = type;
 }
@@ -543,20 +717,19 @@ void set_ia32_Const_type(ir_node *node, int type) {
  * Copy the attributes from an ia32_Const to an Immop (Add_i, Sub_i, ...) node
  */
 void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) {
-       asmop_attr *na = get_ia32_attr(node);
-       asmop_attr *ca = get_ia32_attr(cnst);
+       ia32_attr_t *na = get_ia32_attr(node);
+       ia32_attr_t *ca = get_ia32_attr(cnst);
 
        assert((is_ia32_Const(cnst) || is_ia32_fConst(cnst)) && "Need ia32_Const to set Immop attr");
 
        na->tp = ca->tp;
        na->tv = ca->tv;
 
-       if (ca->old_ir) {
-               na->old_ir = xcalloc(1, sizeof(*(ca->old_ir)));
-               memcpy(na->old_ir, ca->old_ir, sizeof(*(ca->old_ir)));
+       if (ca->sc) {
+               na->sc = copy_str(na->sc, ca->sc);
        }
        else {
-               na->old_ir = NULL;
+               na->sc = NULL;
        }
 }
 
@@ -564,20 +737,21 @@ void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) {
  * Copy the attributes from a Const to an ia32_Const
  */
 void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
-       asmop_attr *attr = get_ia32_attr(ia32_cnst);
+       ia32_attr_t *attr = get_ia32_attr(ia32_cnst);
 
        assert((is_ia32_Const(ia32_cnst) || is_ia32_fConst(ia32_cnst)) && "Need ia32_Const to set Const attr");
 
        switch (get_irn_opcode(cnst)) {
                case iro_Const:
-                       attr->tp = asmop_Const;
-                       attr->tv = get_Const_tarval(cnst);
+                       attr->tp   = ia32_Const;
+                       attr->tv   = get_Const_tarval(cnst);
+                       attr->cnst = set_cnst_from_tv(attr->cnst, attr->tv);
                        break;
                case iro_SymConst:
-                       attr->tp     = asmop_SymConst;
-                       attr->tv     = NULL;
-                       attr->old_ir = xcalloc(1, sizeof(*cnst));
-                       memcpy(attr->old_ir, cnst, sizeof(*cnst));
+                       attr->tp   = ia32_SymConst;
+                       attr->tv   = NULL;
+                       attr->sc   = copy_str(attr->sc, get_sc_name(cnst));
+                       attr->cnst = attr->sc;
                        break;
                case iro_Unknown:
                        assert(0 && "Unknown Const NYI");
@@ -588,19 +762,37 @@ void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
 }
 
 /**
- * Sets the AddrMode attribute
+ * Sets the AddrMode(S|D) attribute
+ */
+void set_ia32_AddrMode(ir_node *node, char direction) {
+       ia32_attr_t *attr = get_ia32_attr(node);
+
+       switch (direction) {
+               case 'D':
+                       attr->tp = ia32_AddrModeD;
+                       break;
+               case 'S':
+                       attr->tp = ia32_AddrModeS;
+                       break;
+               default:
+                       assert(0 && "wrong AM type");
+       }
+}
+
+/**
+ * Returns whether or not the node is an AddrModeS node.
  */
-void set_ia32_AddrMode(ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
-       attr->tp         = asmop_AddrMode;
+int is_ia32_AddrModeS(ir_node *node) {
+       ia32_attr_t *attr = get_ia32_attr(node);
+       return (attr->tp == ia32_AddrModeS);
 }
 
 /**
- * Returns whether or not the node is an AddrMode node.
+ * Returns whether or not the node is an AddrModeD node.
  */
-int is_ia32_AddrMode(ir_node *node) {
-       asmop_attr *attr = get_ia32_attr(node);
-       return (attr->tp == asmop_AddrMode);
+int is_ia32_AddrModeD(ir_node *node) {
+       ia32_attr_t *attr = get_ia32_attr(node);
+       return (attr->tp == ia32_AddrModeD);
 }
 
 
index 5b3478d..c0b4b26 100644 (file)
@@ -30,47 +30,52 @@ const char *get_sc_name(ir_node *symc);
 /**
  * Returns the attributes of an ia32 node.
  */
-asmop_attr *get_ia32_attr(const ir_node *node);
+ia32_attr_t *get_ia32_attr(const ir_node *node);
 
 /**
  * Gets the type of an ia32 node.
  */
-asmop_type_t get_ia32_op_type(const ir_node *node);
+ia32_op_type_t get_ia32_op_type(const ir_node *node);
 
 /**
  * Sets the type of an ia32 node.
  */
-void set_ia32_op_type(const ir_node *node, asmop_type_t tp);
+void set_ia32_op_type(ir_node *node, ia32_op_type_t tp);
 
 /**
- * Gets the addr mode type of an ia32 node
+ * Gets the supported addrmode of an ia32 node
  */
-addrmode_type_t get_ia32_am_type(const ir_node *node);
+ia32_am_type_t get_ia32_am_support(const ir_node *node);
 
 /**
- * Sets the addr mode type of an ia32 node
+ * Sets the supported addrmode of an ia32 node
  */
-void set_ia32_am_type(const ir_node *node, addrmode_type_t am_tp);
+void set_ia32_am_support(ir_node *node, ia32_am_type_t am_tp);
 
 /**
- * Gets the addr mode offset.
+ * Gets the joined addrmode offset.
  */
-tarval *get_ia32_am_offs(const ir_node *node);
+char *get_ia32_am_offs(const ir_node *node);
 
 /**
- * Sets the offset for addr mode.
+ * Adds an offset for addrmode.
  */
-void set_ia32_am_offs(ir_node *node, tarval *am_offs);
+void add_ia32_am_offs(ir_node *node, char *offset);
+
+/**
+ * Subs an offset for addrmode.
+ */
+void sub_ia32_am_offs(ir_node *node, char *offset);
 
 /**
  * Gets the addr mode const.
  */
-tarval *get_ia32_am_const(const ir_node *node);
+int get_ia32_am_scale(const ir_node *node);
 
 /**
  * Sets the const for addr mode.
  */
-void set_ia32_am_const(ir_node *node, tarval *am_const);
+void set_ia32_am_scale(ir_node *node, int scale);
 
 /**
  * Return the tarval of an immediate operation or NULL in case of SymConst
@@ -83,14 +88,19 @@ tarval *get_ia32_Immop_tarval(const ir_node *node);
 void set_ia32_Immop_tarval(ir_node *node, tarval *tv);
 
 /**
- * Return the old_ir attribute.
+ * Return the sc attribute.
+ */
+char *get_ia32_sc(const ir_node *node);
+
+/**
+ * Sets the sc attribute.
  */
-ir_node *get_ia32_old_ir(const ir_node *node);
+void set_ia32_sc(ir_node *node, char *sc);
 
 /**
- * Sets the old_ir attribute.
+ * Gets the string representation of the internal const (tv or symconst)
  */
-void set_ia32_old_ir(ir_node *node, ir_node *old_ir);
+char *get_ia32_cnst(ir_node *node);
 
 /**
  * Returns the argument register requirements of an ia32 node.
@@ -165,12 +175,12 @@ int get_ia32_n_res(const ir_node *node);
 /**
  * Returns the flavour of an ia32 node,
  */
-op_flavour_t get_ia32_flavour(const ir_node *node);
+ia32_op_flavour_t get_ia32_flavour(const ir_node *node);
 
 /**
  * Sets the flavour of an ia32 node to flavour_Div/Mod/DivMod/Mul/Mulh.
  */
-void set_ia32_flavour(ir_node *node, op_flavour_t op_flav);
+void set_ia32_flavour(ir_node *node, ia32_op_flavour_t op_flav);
 
 /**
  * Returns the projnum code.
@@ -217,18 +227,19 @@ void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst);
 
 /**
  * Sets the AddrMode attribute
+ * @param direction The "direction" of AM ('S' source or 'D' destination)
  */
-void set_ia32_AddrMode(ir_node *node);
+void set_ia32_AddrMode(ir_node *node, char direction);
 
 /**
- * Returns whether or not the node is an AddrMode node.
+ * Returns whether or not the node is an AddrModeS node.
  */
-int is_ia32_AddrMode(ir_node *node);
+int is_ia32_AddrModeS(ir_node *node);
 
 /**
- * Checks whether or not an ir_node is an ia32 node
+ * Returns whether or not the node is an AddrModeD node.
  */
-int is_ia32_irn(const ir_node *node);
+int is_ia32_AddrModeD(ir_node *node);
 
 /* Include the generated headers */
 #include "gen_ia32_new_nodes.h"
index 653f53d..9c7e7e7 100644 (file)
@@ -1,47 +1,46 @@
 #ifndef _IA32_NODES_ATTR_H_
 #define _IA32_NODES_ATTR_H_
 
+#include <obstack.h>
+
 #include "firm_types.h"
 #include "../bearch.h"
 
-typedef enum { flavour_Div = 1, flavour_Mod, flavour_DivMod, flavour_Mul, flavour_Mulh } op_flavour_t;
+typedef enum { flavour_Div = 1, flavour_Mod, flavour_DivMod, flavour_Mul, flavour_Mulh } ia32_op_flavour_t;
 typedef enum { pn_EAX, pn_EDX } pn_ia32_Register;
-typedef enum { asmop_Normal, asmop_Const, asmop_SymConst, asmop_AddrMode } asmop_type_t;
+typedef enum { ia32_Normal, ia32_Const, ia32_SymConst, ia32_AddrModeD, ia32_AddrModeS } ia32_op_type_t;
 typedef        enum {
-       am_Reg = 1,          /**<<  (%reg)              */
-       am_OffsReg,          /**<< o(%reg)              */
-       am_RegReg,           /**<<  (%reg, %reg)        */
-       am_RegConst,         /**<<  (    , %reg, const) */
-       am_OffsRegConst,     /**<< o(    , %reg, const) */
-       am_OffsRegReg,       /**<< o(%reg, %reg)        */
-       am_RegRegConst,      /**<<  (%reg, %reg, const) */
-       am_OffsRegRegConst   /**<< o(%reg, %reg, const) */
-} addrmode_type_t;
+       ia32_am_None   = 0,   /**<< no addrmode support */
+       ia32_am_Dest   = 1,   /**<< addrmode for destination only */
+       ia32_am_Source = 2,   /**<< addrmode for source only */
+       ia32_am_Full   = 3    /**<< full addmode support */
+} ia32_am_type_t;
 
 typedef struct _ia32_register_req_t {
        const arch_register_req_t req;
        int pos;   /**<< in case of "should be same/different" we need to remember the pos to get the irn */
 } ia32_register_req_t;
 
-typedef struct _ia32_asmop_attr {
-       asmop_type_t    tp;      /**<< ia32 node type */
-       addrmode_type_t am_tp;   /**<< addr mode type */
+typedef struct _ia32_attr_t {
+       ia32_op_type_t tp;           /**<< ia32 node type */
+       ia32_am_type_t am_support;   /**<< indicates addrmode type supported by this node */
 
-       tarval  *am_offs;  /**<< offset for AddrMode */
-       tarval  *am_const; /**<< shift const for AddrMode */
+       struct obstack *am_offs;  /**<< offsets for AddrMode */
+       int             am_scale; /**<< addrmode scale for index register */
 
-       tarval  *tv;       /**<< tarval for immediate operations */
-       ir_node *old_ir;   /**<< old ir node to avoid duplicating information (symconst in case of asmop_SymConst) */
+       tarval *tv;   /**<< tarval for immediate operations */
+       char   *sc;   /**<< symconst name */
+       char   *cnst; /**<< points to the string representation of the constant value (either tv or sc) */
 
-       op_flavour_t     op_flav;   /**<< flavour of an op (flavour_Div/Mod/DivMod/Mul/Mulh) */
-       long             pn_code;   /**<< projnum "types" (e.g. indicate compare operators and argument numbers) */
-       long             n_res;     /**<< number of results */
-       arch_irn_flags_t flags;     /**<< indicating if spillable and/or rematerializeable */
+       ia32_op_flavour_t op_flav;   /**<< flavour of an op (flavour_Div/Mod/DivMod/Mul/Mulh) */
+       long              pn_code;   /**<< projnum "types" (e.g. indicate compare operators and argument numbers) */
+       long              n_res;     /**<< number of results */
+       arch_irn_flags_t  flags;     /**<< indicating if spillable and/or rematerializeable */
 
        const ia32_register_req_t **in_req;  /**<< register requirements for arguments */
        const ia32_register_req_t **out_req; /**<< register requirements for results */
 
        const arch_register_t **slots;          /**<< register slots for assigned registers */
-} asmop_attr;
+} ia32_attr_t;
 
 #endif /* _IA32_NODES_ATTR_H_ */
index 3b5c14d..a23a2c7 100644 (file)
@@ -12,15 +12,17 @@ $arch = "ia32";
 # %nodes = (
 #
 # <op-name> => {
-#   "op_flags" => "N|L|C|X|I|F|Y|H|c|K",
-#   "arity"    => "0|1|2|3|variable|dynamic|all",
-#   "state"    => "floats|pinned",
-#   "args"     => [
-#                   { "type" => "type 1", "name" => "name 1" },
-#                   { "type" => "type 2", "name" => "name 2" },
-#                   ...
-#                 ],
-#   "comment"  => "any comment for constructor",
+#   "op_flags"  => "N|L|C|X|I|F|Y|H|c|K",
+#   "irn_flags" => "R|N|I"
+#   "arity"     => "0|1|2|3 ... |variable|dynamic|all",
+#   "state"     => "floats|pinned",
+#   "args"      => [
+#                    { "type" => "type 1", "name" => "name 1" },
+#                    { "type" => "type 2", "name" => "name 2" },
+#                    ...
+#                  ],
+#   "comment"   => "any comment for constructor",
+#   "emit"      => "emit code with templates",
 #   "rd_constructor" => "c source code which constructs an ir_node"
 # },
 #
@@ -28,6 +30,7 @@ $arch = "ia32";
 #
 # ); # close the %nodes initializer
 
+# op_flags: flags for the operation, OPTIONAL (default is "N")
 # the op_flags correspond to the firm irop_flags:
 #   N   irop_flag_none
 #   L   irop_flag_labeled
@@ -40,7 +43,11 @@ $arch = "ia32";
 #   c   irop_flag_constlike
 #   K   irop_flag_keep
 #
-# op_flags: flags for the operation, OPTIONAL (default is "N")
+# irn_flags: special node flags, OPTIONAL (default is 0)
+# following irn_flags are supported:
+#   R   rematerializeable
+#   N   not spillable
+#   I   ignore for register allocation
 #
 # state: state of the operation, OPTIONAL (default is "pinned")
 #
@@ -81,26 +88,27 @@ $arch = "ia32";
 #       caller save registers and in the correct order, otherwise it will break
 #       the magic!
 %reg_classes = (
-  "general_purpose" => [
-                         { "name" => "eax", "type" => 2 },
-                         { "name" => "edx", "type" => 2 },
-                         { "name" => "ebx", "type" => 3 },
-                         { "name" => "ecx", "type" => 2 },
-                         { "name" => "esi", "type" => 3 },
-                         { "name" => "edi", "type" => 3 },
-                         { "name" => "ebp", "type" => 3 },
-                         { "name" => "esp", "type" => 4 }  # we don't want esp to be assigned
-                       ],
-  "floating_point"  => [
-                         { "name" => "xmm0", "type" => 2 },
-                         { "name" => "xmm1", "type" => 2 },
-                         { "name" => "xmm2", "type" => 2 },
-                         { "name" => "xmm3", "type" => 2 },
-                         { "name" => "xmm4", "type" => 2 },
-                         { "name" => "xmm5", "type" => 2 },
-                         { "name" => "xmm6", "type" => 2 },
-                         { "name" => "xmm7", "type" => 2 },
-                       ]
+  "gp" => [
+            { "name" => "eax", "type" => 2 },
+            { "name" => "edx", "type" => 2 },
+            { "name" => "ebx", "type" => 3 },
+            { "name" => "ecx", "type" => 2 },
+            { "name" => "esi", "type" => 3 },
+            { "name" => "edi", "type" => 3 },
+            { "name" => "ebp", "type" => 3 },
+            { "name" => "esp", "type" => 4 }, # we don't want esp to be assigned
+            { "name" => "xxx", "type" => 4 }  # we need a dummy register for NoReg and Unknown nodes
+          ],
+  "fp" => [
+            { "name" => "xmm0", "type" => 2 },
+            { "name" => "xmm1", "type" => 2 },
+            { "name" => "xmm2", "type" => 2 },
+            { "name" => "xmm3", "type" => 2 },
+            { "name" => "xmm4", "type" => 2 },
+            { "name" => "xmm5", "type" => 2 },
+            { "name" => "xmm6", "type" => 2 },
+            { "name" => "xmm7", "type" => 2 }
+          ]
 ); # %reg_classes
 
 #--------------------------------------------------#
@@ -129,144 +137,90 @@ $arch = "ia32";
 
 # commutative operations
 
-"Add" => {
-  "op_flags"    => "C",
-  "arity"       => 2,
-  "remat"       => 1,
-  "comment"     => "construct Add: Add(a, b) = Add(b, a) = a + b",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. addl %S2, %D1\t\t\t/* Add(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
+# NOTE:
+# All nodes supporting Addressmode have 5 INs:
+# 1 - base    r1 == NoReg in case of no AM or no base
+# 2 - index   r2 == NoReg in case of no AM or no index
+# 3 - op1     r3 == always present
+# 4 - op2     r4 == NoReg in case of immediate operation
+# 5 - mem     NoMem in case of no AM otherwise it takes the mem from the Load
 
-"Add_i" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct Add: Add(a, const) = Add(const, a) = a + const",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. addl %C, %D1\t\t\t/* Add(%C, %S1) -> %D1, (%A1, const) */'
+"Add" => {
+  "op_flags"  => "C",
+  "irn_flags" => "R",
+  "comment"   => "construct Add: Add(a, b) = Add(b, a) = a + b",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. add %ia32_emit_binop\t\t\t/* Add(%A1, %A2) -> %D1 */'
 },
 
 "Mul" => {
-  "op_flags"    => "C",
-  "arity"       => 2,
-  "comment"     => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "eax in_r1", "edx in_r2" ] },
-  "emit"        =>
-'  if (mode_is_signed(get_irn_mode(n))) {
-4. imull %S2\t\t\t/* signed Mul(%S1, %S2) -> %D1, (%A1, %A2) */
-  }
-  else {
-4. mull %S2\t\t\t/* unsigned Mul(%S1, %S2) -> %D1, (%A1, %A2) */
-  }
-'
+  "op_flags"  => "C",
+  "irn_flags" => "A",
+  "comment"   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. imul %ia32_emit_binop\t\t\t/* Mul(%A1, %A2) -> %D1 */'
 },
 
-"Mul_i" => {
-  "state"       => "pinned",
-  "arity"       => 1,
-  "comment"     => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "eax in_r1", "edx" ] },
-  "emit"        =>
-'  if (mode_is_signed(get_irn_mode(n))) {
-4. imull %C\t\t\t/* signed Mul(%C, %S1) -> %D1, (%A1, const) */
-  }
-  else {
-4. mull %C\t\t\t/* unsigned Mul(%C, %S1) -> %D1, (%A1, const) */
-  }
-'
+# Mulh is an exception from the 4 INs with AM because the target is always EAX:EDX
+"Mulh" => {
+  "op_flags"  => "C",
+  "comment"   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "eax in_r1", "edx in_r2" ] },
+  "emit"      => '. imul %ia32_emit_unop\t\t\t/* Mulh(%A1, %A2) -> %D1 */ '
 },
 
 "And" => {
-  "op_flags"    => "C",
-  "arity"       => 2,
-  "remat"       => 1,
-  "comment"     => "construct And: And(a, b) = And(b, a) = a AND b",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. andl %S2, %D1\t\t\t/* And(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"And_i" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct And: And(a, const) = And(const, a) = a AND const",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. andl %C, %D1\t\t\t/* And(%C, %S1) -> %D1, (%A1, const) */'
+  "op_flags"  => "C",
+  "irn_flags" => "R",
+  "comment"   => "construct And: And(a, b) = And(b, a) = a AND b",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. and %ia32_emit_binop\t\t\t/* And(%A1, %A2) -> %D1 */'
 },
 
 "Or" => {
-  "op_flags"    => "C",
-  "arity"       => 2,
-  "remat"       => 1,
-  "comment"     => "construct Or: Or(a, b) = Or(b, a) = a OR b",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. orl %S2, %D1\t\t\t/* Or(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"Or_i" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct Or: Or(a, const) = Or(const, a) = a OR const",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. orl %C, %D1\t\t\t/* Or(%C, %S1) -> %D1, (%A1, const) */'
+  "op_flags"  => "C",
+  "irn_flags" => "R",
+  "comment"   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. or %ia32_emit_binop\t\t\t/* Or(%A1, %A2) -> %D1 */'
 },
 
 "Eor" => {
-  "op_flags"    => "C",
-  "arity"       => 2,
-  "remat"       => 1,
-  "comment"     => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. xorl %S2, %D1\t\t\t/* Xor(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"Eor_i" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. xorl %C, %D1\t\t\t/* Xor(%C, %S1) -> %D1, (%A1, const) */'
+  "op_flags"  => "C",
+  "irn_flags" => "R",
+  "comment"   => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. xor %ia32_emit_binop\t\t\t/* Xor(%A1, %A2) -> %D1 */'
 },
 
 "Max" => {
-  "op_flags"    => "C",
-  "arity"       => 2,
-  "remat"       => 1,
-  "comment"     => "construct Max: Max(a, b) = Max(b, a) = a > b ? a : b",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        =>
-'2. cmpl %S2, %S1\t\t\t/* prepare Max (%S1 should be %D1), (%A1, %A2) */
+  "op_flags"  => "C",
+  "irn_flags" => "R",
+  "comment"   => "construct Max: Max(a, b) = Max(b, a) = a > b ? a : b",
+  "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
+  "emit"      =>
+'2. cmp %S1, %S2\t\t\t/* prepare Max (%S1 - %S2), (%A1, %A2) */
   if (mode_is_signed(get_irn_mode(n))) {
-4.  cmovl %S2, %D1\t\t\t/* %S1 is less %S2 */
+4.  cmovl %D1, %S2\t\t\t/* %S1 is less %S2 */
   }
   else {
-4.  cmovb %S2, %D1\t\t\t/* %S1 is below %S2 */
+4.  cmovb %D1, %S2\t\t\t/* %S1 is below %S2 */
   }
 '
 },
 
 "Min" => {
-  "op_flags"    => "C",
-  "arity"       => 2,
-  "remat"       => 1,
-  "comment"     => "construct Min: Min(a, b) = Min(b, a) = a < b ? a : b",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        =>
-'2. cmpl %S2, %S1\t\t\t/* prepare Min (%S1 should be %D1), (%A1, %A2) */
+  "op_flags"  => "C",
+  "irn_flags" => "R",
+  "comment"   => "construct Min: Min(a, b) = Min(b, a) = a < b ? a : b",
+  "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
+  "emit"      =>
+'2. cmp %S1, %S2\t\t\t/* prepare Min (%S1 - %S2), (%A1, %A2) */
   if (mode_is_signed(get_irn_mode(n))) {
-2.  cmovg %S2, %D1\t\t\t/* %S1 is greater %S2 */
+2.  cmovg %D1, %S2\t\t\t/* %S1 is greater %S2 */
   }
   else {
-2.  cmova %S2, %D1\t\t\t/* %S1 is above %S2 */
+2.  cmova %D1, %S2, %D1\t\t\t/* %S1 is above %S2 */
   }
 '
 },
@@ -274,202 +228,128 @@ $arch = "ia32";
 # not commutative operations
 
 "Sub" => {
-  "arity"       => 2,
-  "remat"       => 1,
-  "comment"     => "construct Sub: Sub(a, b) = a - b",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. subl %S2, %D1\t\t\t/* Sub(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"Sub_i" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct Sub: Sub(a, const) = a - const",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. subl %C, %D1\t\t\t/* Sub(%S1, %C) -> %D1, (%A1, const) */'
+  "irn_flags" => "R",
+  "comment"   => "construct Sub: Sub(a, b) = a - b",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. sub %ia32_emit_binop\t\t\t/* Sub(%A1, %A2) -> %D1 */'
 },
 
 "DivMod" => {
-  "op_flags"    => "F|L",
-  "state"       => "exc_pinned",
-  "arity"       => 4,
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose", "general_purpose", "none" ], "out" => [ "eax in_r1", "edx in_r3" ] },
-  "emit"        =>
+  "op_flags" => "F|L",
+  "state"    => "exc_pinned",
+  "reg_req"  => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "eax in_r1", "edx in_r3" ] },
+  "emit"     =>
 '  if (mode_is_signed(get_irn_mode(n))) {
-4.  idivl %S2\t\t\t/* signed DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
+4.  idiv %S2\t\t\t/* signed DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
   }
   else {
-4.  divl %S2\t\t\t/* unsigned DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
+4.  div %S2\t\t\t/* unsigned DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
   }
 '
 },
 
 "Shl" => {
-  "arity"       => 2,
-  "remat"       => 1,
-  "comment"     => "construct Shl: Shl(a, b) = a << b",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. shll %S2, %D1\t\t\t/* Shl(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"Shl_i" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct Shl: Shl(a, const) = a << const",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. shll %C, %D1\t\t\t/* Shl(%S1, %C) -> %D1, (%A1, const) */'
+  "irn_flags" => "R",
+  "comment"   => "construct Shl: Shl(a, b) = a << b",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. shl %ia32_emit_binop\t\t\t/* Shl(%A1, %A2) -> %D1 */'
 },
 
 "Shr" => {
-  "arity"       => 2,
-  "remat"       => 1,
-  "comment"     => "construct Shr: Shr(a, b) = a >> b",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. shrl %S2, %D1\t\t\t/* Shr(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"Shr_i" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct Shr: Shr(a, const) = a >> const",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. shrl %C, %D1\t\t\t/* Shr(%S1, %C) -> %D1, (%A1, const) */'
+  "irn_flags" => "R",
+  "comment"   => "construct Shr: Shr(a, b) = a >> b",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. shr %ia32_emit_binop\t\t\t/* Shr(%A1, %A2) -> %D1 */'
 },
 
 "Shrs" => {
-  "arity"       => 2,
-  "remat"       => 1,
-  "comment"     => "construct Shrs: Shrs(a, b) = a >> b",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. sarl %S2, %D1\t\t\t/* Shrs(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"Shrs_i" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct Shrs: Shrs(a, const) = a >> const",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. sarl %C, %D1\t\t\t/* Shrs(%S1, %C) -> %D1, (%A1, const) */'
+  "irn_flags" => "R",
+  "comment"   => "construct Shrs: Shrs(a, b) = a >> b",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. sar %ia32_emit_binop\t\t\t/* Shrs(%A1, %A2) -> %D1 */'
 },
 
 "RotR" => {
-  "arity"       => 2,
-  "remat"       => 1,
+  "irn_flags" => "R",
   "comment"     => "construct RotR: RotR(a, b) = a ROTR b",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. rorl %S2, %D1\t\t\t/* RotR(%S1, %S2) -> %D1, (%A1, %A2) */'
+  "reg_req"     => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] },
+  "emit"        => '. ror %ia32_emit_binop\t\t\t/* RotR(%A1, %A2) -> %D1 */'
 },
 
 "RotL" => {
-  "arity"       => 2,
-  "remat"       => 1,
-  "comment"     => "construct RotL: RotL(a, b) = a ROTL b",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. roll %S2, %D1\t\t\t/* RotL(%S1, %S2) -> %D1, (%A1, %A2) */'
+  "irn_flags" => "R",
+  "comment"   => "construct RotL: RotL(a, b) = a ROTL b",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. rol %ia32_emit_binop\t\t\t/* RotL(%A1, %A2) -> %D1 */'
 },
 
-"RotL_i" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct RotL: RotL(a, const) = a ROTL const",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. roll %C, %D1\t\t\t/* RotL(%S1, %C) -> %D1, (%A1, const) */'
-},
+# unary operations
 
 "Minus" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct Minus: Minus(a) = -a",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. negl %D1\t\t\t/* Neg(%S1) -> %D1, (%A1) */'
+  "irn_flags" => "R",
+  "comment"   => "construct Minus: Minus(a) = -a",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. neg %ia32_emit_unop\t\t\t/* Neg(%A1) -> %D1, (%A1) */'
 },
 
 "Inc" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct Increment: Inc(a) = a++",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. incl %D1\t\t\t/* Inc(%S1) -> %D1, (%A1) */'
+  "irn_flags" => "R",
+  "comment"   => "construct Increment: Inc(a) = a++",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. inc %ia32_emit_unop\t\t\t/* Inc(%S1) -> %D1, (%A1) */'
 },
 
 "Dec" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct Decrement: Dec(a) = a--",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. decl %D1\t\t\t/* Dec(%S1) -> %D1, (%A1) */'
+  "irn_flags" => "R",
+  "comment"   => "construct Decrement: Dec(a) = a--",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. dec %ia32_emit_unop\t\t\t/* Dec(%S1) -> %D1, (%A1) */'
 },
 
 "Not" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct Not: Not(a) = !a",
-  "check_inout" => 1,
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
-  "emit"        => '. notl %D1\t\t\t/* Not(%S1) -> %D1, (%A1) */'
+  "irn_flags" => "R",
+  "comment"   => "construct Not: Not(a) = !a",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. not %ia32_emit_unop\t\t\t/* Not(%S1) -> %D1, (%A1) */'
 },
 
 # other operations
 
 "Conv" => {
   "arity"    => 1,
-  "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
+  "reg_req"  => { "in" => [ "gp" ], "out" => [ "in_r1" ] },
   "comment"  => "construct Conv: Conv(a) = (conv)a"
 },
 
 "CondJmp" => {
-  "op_flags" => "C|L|X|Y",
-  "arity"    => 2,
-  "comment"  => "construct conditional jump: CMP A, B && JMPxx LABEL",
-  "reg_req"  => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "none", "none" ] },
-},
-
-"CondJmp_i" => {
-  "op_flags" => "L|X|Y",
-  "arity"    => 1,
-  "comment"  => "construct conditional jump: CMP A, const && JMPxx LABEL",
-  "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "none", "none" ] },
+  "op_flags"  => "C|L|X|Y",
+  "comment"   => "construct conditional jump: CMP A, B && JMPxx LABEL",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "none", "none" ] },
 },
 
 "SwitchJmp" => {
-  "op_flags" => "L|X|Y",
-  "arity"    => 1,
-  "comment"  => "construct switch",
-  "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "none" ] },
+  "op_flags"  => "L|X|Y",
+  "comment"   => "construct switch",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
 },
 
 "Const" => {
-  "op_flags" => "c",
-  "arity"    => "0",
-  "remat"    => 1,
-  "comment"  => "represents an integer constant",
-  "reg_req"  => { "out" => [ "general_purpose" ] },
-  "emit"     => '. movl %C, %D1\t\t\t/* Mov Const into register */',
-  "cmp_attr" =>
+  "op_flags"  => "c",
+  "irn_flags" => "R",
+  "comment"   => "represents an integer constant",
+  "reg_req"   => { "out" => [ "gp" ] },
+  "emit"      => '. mov %D1, %C\t\t\t/* Mov Const into register */',
+  "cmp_attr"  =>
 '
   if (attr_a->tp == attr_b->tp) {
-    if (attr_a->tp == asmop_SymConst) {
-      if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
+    if (attr_a->tp == ia32_SymConst) {
+      if (attr_a->sc == NULL || attr_b->sc == NULL)
         return 1;
       else
-        return strcmp(get_sc_name(attr_a->old_ir), get_sc_name(attr_b->old_ir));
+        return strcmp(attr_a->sc, attr_b->sc);
     }
     else {
-      if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
+      if (attr_a->tv == NULL || attr_b->tv == NULL)
         return 1;
 
       if (tarval_cmp(attr_a->tv, attr_b->tv) == pn_Cmp_Eq)
@@ -483,55 +363,44 @@ $arch = "ia32";
 '
 },
 
-"Cltd" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "comment"     => "construct Cltd: sign extend EAX -> EDX:EAX",
-  "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "eax in_r1", "edx" ] },
-  "emit"        => '. cltd\t\t\t/* sign extend EAX -> EDX:EAX, (%A1) */'
+"Cdq" => {
+  "irn_flags" => "R",
+  "comment"   => "construct CDQ: sign extend EAX -> EDX:EAX",
+  "reg_req"   => { "in" => [ "gp" ], "out" => [ "eax in_r1", "edx" ] },
+  "emit"      => '. cdq\t\t\t/* sign extend EAX -> EDX:EAX, (%A1) */'
 },
 
 # Load / Store
 
 "Load" => {
-  "op_flags" => "L|F",
-  "state"    => "exc_pinned",
-  "arity"    => 2,
-  "remat"    => 1,
-  "comment"  => "construct Load: Load(ptr, mem) = LD ptr -> reg",
-  "reg_req"  => { "in" => [ "general_purpose", "none" ], "out" => [ "general_purpose" ] },
-  "emit"     => '. movl %O(%S1), %D1\t\t\t/* Load((%S1)) -> %D1, (%A1) */'
+  "op_flags"  => "L|F",
+  "irn_flags" => "R",
+  "state"     => "exc_pinned",
+  "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+  "reg_req"   => { "in" => [ "gp", "gp", "none" ], "out" => [ "gp" ] },
+  "emit"      => '. mov %D1, %ia32_emit_am\t\t\t/* Load((%A1)) -> %D1 */'
 },
 
 "Store" => {
-  "op_flags" => "L|F",
-  "state"    => "exc_pinned",
-  "arity"    => 3,
-  "remat"    => 1,
-  "comment"  => "construct Store: Store(ptr, val, mem) = ST ptr,val",
-  "reg_req"  => { "in" => [ "general_purpose", "general_purpose", "none" ] },
-  "emit"     => '. movl %S2, %O(%S1)\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */'
+  "op_flags"  => "L|F",
+  "state"     => "exc_pinned",
+  "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ] },
+  "emit"      => '. mov %ia32_emit_am, %S3\t\t\t/* Store(%A2) -> (%A1) */'
 },
 
 "Lea" => {
-  "arity"    => 2,
-  "comment"  => "construct Lea: Lea(a,b) = lea offs(a,b,const) | res = a + b * const + offs with const = 0,1,2,4,8",
-  "reg_req"  => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] },
-  "emit"     => '. leal %O(%S1, %S2, %C), %D1\t\t/* %D1 = %S1 + %S2 << %C + %O, (%A1, %A2) */'
-},
-
-"Lea_i" => {
-  "arity"    => 1,
-  "comment"  => "construct Lea: Lea(a) = lea offs(a) | res = a + offs",
-  "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
-  "emit"     => '. leal %C(%S1), %D1\t\t\t/* %D1 = %S1 + %C, (%A1)*/'
+  "irn_flags" => "R",
+  "comment"   => "construct Lea: Lea(a,b) = lea [a+b*const+offs] | res = a + b * const + offs with const = 0,1,2,4,8",
+  "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
+  "emit"      => '. lea %D1, %ia32_emit_am\t\t/* %D1 = %S1 + %S2 << %C + %O, (%A1, %A2) */'
 },
 
 "StackParam" => {
   "arity"    => 1,
   "remat"    => 1,
   "comment"  => "constructs a Stack Parameter to retrieve a parameter from Stack",
-  "reg_req"  => { "in" => [ "none" ], "out" => [ "general_purpose" ] },
+  "reg_req"  => { "in" => [ "none" ], "out" => [ "gp" ] },
   "cmp_attr" =>
 '
   return (attr_a->pn_code != attr_b->pn_code);
@@ -541,7 +410,7 @@ $arch = "ia32";
 "StackArg" => {
   "arity"    => 2,
   "comment"  => "constructs a Stack Argument to pass an argument on Stack",
-  "reg_req"  => { "in" => [ "none", "general_purpose" ], "out" => [ "none" ] },
+  "reg_req"  => { "in" => [ "none", "gp" ], "out" => [ "none" ] },
   "cmp_attr" =>
 '
   return (attr_a->pn_code != attr_b->pn_code);
@@ -560,106 +429,108 @@ $arch = "ia32";
 # commutative operations
 
 "fAdd" => {
-  "op_flags"    => "C",
-  "arity"       => 2,
-  "remat"       => 1,
-  "check_inout" => 1,
-  "comment"     => "construct SSE Add: Add(a, b) = Add(b, a) = a + b",
-  "reg_req"     => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] },
-  "emit"        => '. add%M %S2, %D1\t\t\t/* SSE Add(%S1, %S2) -> %D1 */'
+  "op_flags"  => "C",
+  "irn_flags" => "R",
+  "comment"   => "construct SSE Add: Add(a, b) = Add(b, a) = a + b",
+  "reg_req"   => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. adds%M %ia32_emit_binop\t\t\t/* SSE Add(%A1, %A2) -> %D1 */'
 },
 
 "fMul" => {
-  "op_flags"    => "C",
-  "arity"       => 2,
-  "check_inout" => 1,
-  "comment"     => "construct SSE Mul: Mul(a, b) = Mul(b, a) = a * b",
-  "reg_req"     => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] },
-  "emit"        =>'. muls%M %S2, %D1\t\t\t/* SSE Mul(%S1, %S2) -> %D1 */'
+  "op_flags"  => "C",
+  "irn_flags" => "R",
+  "comment"   => "construct SSE Mul: Mul(a, b) = Mul(b, a) = a * b",
+  "reg_req"   => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] },
+  "emit"      => '. muls%M %ia32_emit_binop\t\t\t/* SSE Mul(%A1, %A2) -> %D1 */'
 },
 
 "fMax" => {
-  "op_flags"    => "C",
-  "arity"       => 2,
-  "remat"       => 1,
-  "check_inout" => 1,
-  "comment"     => "construct SSE Max: Max(a, b) = Max(b, a) = a > b ? a : b",
-  "reg_req"     => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] },
-  "emit"        =>'. maxs%M %S2, %D1\t\t\t/* SSE Max(%S1, %S2) -> %D1 */'
+  "op_flags"  => "C",
+  "irn_flags" => "R",
+  "comment"   => "construct SSE Max: Max(a, b) = Max(b, a) = a > b ? a : b",
+  "reg_req"   => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] },
+  "emit"      => '. maxs%M %ia32_emit_binop\t\t\t/* SSE Max(%A1, %A2) -> %D1 */'
 },
 
 "fMin" => {
-  "op_flags"    => "C",
-  "arity"       => 2,
-  "remat"       => 1,
-  "check_inout" => 1,
-  "comment"     => "construct SSE Min: Min(a, b) = Min(b, a) = a < b ? a : b",
-  "reg_req"     => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] },
-  "emit"        =>'. mins%M %S2, %D1\t\t\t/* SSE Min(%S1, %S2) -> %D1 */'
+  "op_flags"  => "C",
+  "irn_flags" => "R",
+  "comment"   => "construct SSE Min: Min(a, b) = Min(b, a) = a < b ? a : b",
+  "reg_req"   => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] },
+  "emit"      => '. mins%M %ia32_emit_binop\t\t\t/* SSE Min(%A1, %A2) -> %D1 */'
+},
+
+"fAnd" => {
+  "op_flags"  => "C",
+  "irn_flags" => "R",
+  "comment"   => "construct SSE And: And(a, b) = a AND b",
+  "reg_req"   => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] },
+  "emit"      => '. andp%M %ia32_emit_binop\t\t\t/* SSE And(%A3, %A4) -> %D1 */'
+},
+
+"fOr" => {
+  "op_flags"  => "C",
+  "irn_flags" => "R",
+  "comment"   => "construct SSE Or: Or(a, b) = a OR b",
+  "reg_req"   => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] },
+  "emit"      => '. orp%M %ia32_emit_binop\t\t\t/* SSE Or(%A3, %A4) -> %D1 */'
+},
+
+"fEor" => {
+  "op_flags"  => "C",
+  "irn_flags" => "R",
+  "comment"   => "construct SSE Eor: Eor(a, b) = a XOR b",
+  "reg_req"   => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] },
+  "emit"      => '. xorp%M %ia32_emit_binop\t\t\t/* SSE Xor(%A3, %A4) -> %D1 */'
 },
 
 # not commutative operations
 
 "fSub" => {
-  "arity"       => 2,
-  "remat"       => 1,
-  "check_inout" => 1,
-  "comment"     => "construct SSE Sub: Sub(a, b) = a - b",
-  "reg_req"     => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] },
-  "emit"        => '. subs%M %S2, %D1\t\t\t/* SSE Sub(%S1, %S2) -> %D1 */'
+  "irn_flags" => "R",
+  "comment"   => "construct SSE Sub: Sub(a, b) = a - b",
+  "reg_req"   => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. subs%M %ia32_emit_binop\t\t\t/* SSE Sub(%A1, %A2) -> %D1 */'
 },
 
 "fDiv" => {
-  "arity"       => 2,
-  "remat"       => 1,
-  "check_inout" => 1,
-  "comment"     => "construct SSE Div: Div(a, b) = a / b",
-  "reg_req"     => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] },
-  "emit"        => '. divs%M %S2, %D1\t\t\t/* SSE Div(%S1, %S2) -> %D1 */'
-},
-
-"fMinus" => {
-  "arity"       => 1,
-  "remat"       => 1,
-  "check_inout" => 1,
-  "comment"     => "construct SSE Minus: Minus(a) = -a",
-  "reg_req"     => { "in" => [ "floating_point" ], "out" => [ "in_r1" ] },
-  "emit"        => '. xorp%M c %D1\t\t\t/* SSE Minus(%S1) -> %D1 */'
+  "irn_flags" => "R",
+  "comment"   => "construct SSE Div: Div(a, b) = a / b",
+  "reg_req"   => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r1" ] },
+  "emit"      => '. divs%M %ia32_emit_binop\t\t\t/* SSE Div(%A1, %A2) -> %D1 */'
 },
 
 # other operations
 
 "fConv" => {
   "arity"    => 1,
-  "reg_req"  => { "in" => [ "floating_point" ], "out" => [ "general_purpose" ] },
+  "reg_req"  => { "in" => [ "fp" ], "out" => [ "gp" ] },
   "comment"  => "construct Conv: Conv(a) = (conv)a"
 },
 
 "fCondJmp" => {
-  "op_flags" => "C|L|X|Y",
-  "arity"    => 2,
-  "comment"  => "construct conditional jump: CMP A, B && JMPxx LABEL",
-  "reg_req"  => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "none", "none" ] },
+  "op_flags"  => "C|L|X|Y",
+  "comment"   => "construct conditional jump: UCOMIS A, B && JMPxx LABEL",
+  "reg_req"   => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "none", "none" ] },
 },
 
 "fConst" => {
-  "op_flags" => "c",
-  "arity"    => "0",
-  "remat"    => 1,
-  "comment"  => "represents a SSE constant",
-  "reg_req"  => { "out" => [ "floating_point" ] },
-  "emit"     => '. mov%M %C, %D1\t\t\t/* Mov fConst into register */',
-  "cmp_attr" =>
+  "op_flags"  => "c",
+  "irn_flags" => "R",
+  "comment"   => "represents a SSE constant",
+  "reg_req"   => { "out" => [ "fp" ] },
+  "emit"      => '. mov%M %D1, %C\t\t\t/* Load fConst into register */',
+  "cmp_attr"  =>
 '
   if (attr_a->tp == attr_b->tp) {
-    if (attr_a->tp == asmop_SymConst) {
-      if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
+    if (attr_a->tp == ia32_SymConst) {
+      if (attr_a->sc == NULL || attr_b->sc == NULL)
         return 1;
       else
-        return strcmp(get_sc_name(attr_a->old_ir), get_sc_name(attr_b->old_ir));
+        return strcmp(attr_a->sc, attr_b->sc);
     }
     else {
-      if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
+      if (attr_a->tv == NULL || attr_b->tv == NULL)
         return 1;
 
       if (tarval_cmp(attr_a->tv, attr_b->tv) == pn_Cmp_Eq)
@@ -676,30 +547,27 @@ $arch = "ia32";
 # Load / Store
 
 "fLoad" => {
-  "op_flags" => "L|F",
-  "state"    => "exc_pinned",
-  "arity"    => 2,
-  "remat"    => 1,
-  "comment"  => "construct SSE Load: Load(ptr, mem) = LD ptr",
-  "reg_req"  => { "in" => [ "general_purpose", "none" ], "out" => [ "floating_point" ] },
-  "emit"     => '. movl O(%S1), %D1\t\t\t/* Load((%S1)) -> %D1 */'
+  "op_flags"  => "L|F",
+  "irn_flags" => "R",
+  "state"     => "exc_pinned",
+  "comment"   => "construct SSE Load: Load(ptr, mem) = LD ptr",
+  "reg_req"   => { "in" => [ "gp", "gp", "none" ], "out" => [ "fp" ] },
+  "emit"      => '. movs%M %D1, %ia32_emit_am\t\t\t/* Load((%A1)) -> %D1 */'
 },
 
 "fStore" => {
   "op_flags" => "L|F",
   "state"    => "exc_pinned",
-  "arity"    => 3,
-  "remat"    => 1,
   "comment"  => "construct Store: Store(ptr, val, mem) = ST ptr,val",
-  "reg_req"  => { "in" => [ "general_purpose", "floating_point", "none" ] },
-  "emit"     => '. movl %S2, O(%S1)\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */'
+  "reg_req"  => { "in" => [ "gp", "gp", "fp", "none" ] },
+  "emit"     => '. movs%M %ia32_emit_am, %S3\t\t\t/* Store(%S3) -> (%A1) */'
 },
 
 "fStackParam" => {
   "arity"    => 1,
   "remat"    => 1,
   "comment"  => "constructs a Stack Parameter to retrieve a SSE parameter from Stack",
-  "reg_req"  => { "in" => [ "none" ], "out" => [ "floating_point" ] },
+  "reg_req"  => { "in" => [ "none" ], "out" => [ "fp" ] },
   "cmp_attr" =>
 '
   return (attr_a->pn_code != attr_b->pn_code);
@@ -709,7 +577,7 @@ $arch = "ia32";
 "fStackArg" => {
   "arity"    => 2,
   "comment"  => "constructs a Stack Argument to pass an argument on Stack",
-  "reg_req"  => { "in" => [ "none", "floating_point" ], "out" => [ "none" ] },
+  "reg_req"  => { "in" => [ "none", "fp" ], "out" => [ "none" ] },
   "cmp_attr" =>
 '
   return (attr_a->pn_code != attr_b->pn_code);
@@ -757,15 +625,7 @@ $arch = "ia32";
   "state"    => "pinned",
   "arity"    => "2",
   "comment"  => "construct Alloca: allocate memory on Stack",
-  "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }
+  "reg_req"  => { "in" => [ "gp" ], "out" => [ "gp" ] }
 },
 
-"Alloca_i" => {
-  "op_flags" => "L|F",
-  "state"    => "pinned",
-  "arity"    => "1",
-  "comment"  => "construct Alloca: allocate memory on Stack",
-  "reg_req"  => { "out" => [ "general_purpose" ] }
-}
-
 ); # end of %nodes
index 37099db..3eba47c 100644 (file)
 
 extern ir_op *get_op_Mulh(void);
 
+typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
+                                                                         ir_node *op1, ir_node *op2, ir_node *mem, ir_mode *mode);
 
+typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
+                                                                        ir_node *op, ir_node *mem, ir_mode *mode);
+
+/* TEMPORARY WORKAROUND */
+ir_node *be_new_NoReg(ir_graph *irg) {
+       return new_NoMem();
+}
 
 /****************************************************************************************************
  *                  _        _                        __                           _   _
@@ -38,18 +47,189 @@ extern ir_op *get_op_Mulh(void);
  *
  ****************************************************************************************************/
 
-
+#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_ia32_Const(op1) ? op1 : (is_ia32_Const(op2) ? op2 : NULL);
-       else return is_ia32_Const(op2) ? op2 : NULL;
+               return is_cnst(op1) ? op1 : (is_cnst(op2) ? op2 : NULL);
+       else return is_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_ia32_Const(op1) ? op1 : (!is_ia32_Const(op2) ? op2 : NULL);
+       return !is_cnst(op1) ? op1 : (!is_cnst(op2) ? op2 : NULL);
+}
+
+
+/**
+ * Construct a standard binary operation, set AM and immediate if required.
+ *
+ * @param env   The transformation environment
+ * @param op1   The first operand
+ * @param op2   The second operand
+ * @param func  The node constructor function
+ * @return The constructed ia32 node.
+ */
+static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
+       ir_node           *new_op = NULL;
+       ir_mode           *mode   = env->mode;
+       dbg_info          *dbg    = env->dbg;
+       ir_graph          *irg    = env->irg;
+       ir_node           *block  = env->block;
+       firm_dbg_module_t *mod    = env->mod;
+       ir_node           *noreg  = be_new_NoReg(irg);
+       ir_node           *nomem  = new_NoMem();
+       ir_node           *expr_op, *imm_op;
+
+
+       /* check if it's an operation with immediate */
+       if (is_op_commutative(get_irn_op(env->irn))) {
+               imm_op  = get_immediate_op(op1, op2);
+               expr_op = get_expr_op(op1, op2);
+       }
+       else {
+               imm_op  = get_immediate_op(NULL, op2);
+               expr_op = get_expr_op(op1, op2);
+       }
+
+       assert((expr_op || imm_op) && "invalid operands");
+
+       if (!expr_op) {
+               /* We have two consts here: not yet supported */
+               imm_op = NULL;
+       }
+
+       if (mode_is_float(mode)) {
+               /* floating point operations */
+               if (imm_op) {
+
+                       new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
+                       set_ia32_Immop_attr(new_op, imm_op);
+                       set_ia32_am_support(new_op, ia32_am_None);
+               }
+               else {
+                       new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
+                       set_ia32_am_support(new_op, ia32_am_Source);
+               }
+       }
+       else {
+               /* integer operations */
+               if (imm_op) {
+                       /* This is expr + const */
+                       new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
+                       set_ia32_Immop_attr(new_op, imm_op);
+
+                       /* set AM support */
+                       set_ia32_am_support(new_op, ia32_am_Dest);
+               }
+               else {
+                       /* This is a normal operation */
+                       new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
+
+                       /* set AM support */
+                       set_ia32_am_support(new_op, ia32_am_Full);
+               }
+       }
+
+       return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
+}
+
+
+
+/**
+ * Construct a shift/rotate binary operation, sets AM and immediate if required.
+ *
+ * @param env   The transformation environment
+ * @param op1   The first operand
+ * @param op2   The second operand
+ * @param func  The node constructor function
+ * @return The constructed ia32 node.
+ */
+static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
+       ir_node           *new_op = NULL;
+       ir_mode           *mode   = env->mode;
+       dbg_info          *dbg    = env->dbg;
+       ir_graph          *irg    = env->irg;
+       ir_node           *block  = env->block;
+       firm_dbg_module_t *mod    = env->mod;
+       ir_node           *noreg  = be_new_NoReg(irg);
+       ir_node           *nomem  = new_NoMem();
+       ir_node           *expr_op, *imm_op;
+       tarval            *tv;
+
+       assert(! mode_is_float(mode) && "Shift/Rotate with float not supported");
+
+       imm_op  = get_immediate_op(NULL, op2);
+       expr_op = get_expr_op(op1, op2);
+
+       assert((expr_op || imm_op) && "invalid operands");
+
+       if (!expr_op) {
+               /* We have two consts here: not yet supported */
+               imm_op = NULL;
+       }
+
+       /* Limit imm_op within range imm8 */
+       if (imm_op) {
+               tv = get_ia32_Immop_tarval(imm_op);
+
+               if (tv) {
+                       tv = tarval_mod(tv, new_tarval_from_long(32, mode_Iu));
+               }
+               else {
+                       imm_op = NULL;
+               }
+       }
+
+       /* integer operations */
+       if (imm_op) {
+               /* This is shift/rot with const */
+
+               new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
+               set_ia32_Immop_attr(new_op, imm_op);
+       }
+       else {
+               /* This is a normal shift/rot */
+               new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
+       }
+
+       /* set AM support */
+       set_ia32_am_support(new_op, ia32_am_Dest);
+
+       return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
+}
+
+
+/**
+ * Construct a standard unary operation, set AM and immediate if required.
+ *
+ * @param env   The transformation environment
+ * @param op    The operand
+ * @param func  The node constructor function
+ * @return The constructed ia32 node.
+ */
+static ir_node *gen_unop(ia32_transform_env_t *env, ir_node *op, construct_unop_func *func) {
+       ir_node           *new_op = NULL;
+       ir_mode           *mode   = env->mode;
+       dbg_info          *dbg    = env->dbg;
+       ir_graph          *irg    = env->irg;
+       ir_node           *block  = env->block;
+       ir_node           *noreg  = be_new_NoReg(irg);
+       ir_node           *nomem  = new_NoMem();
+
+       new_op = func(dbg, irg, block, noreg, noreg, op, nomem, mode_T);
+
+       if (mode_is_float(mode)) {
+               /* floating point operations don't support implicit store */
+               set_ia32_am_support(new_op, ia32_am_None);
+       }
+       else {
+               set_ia32_am_support(new_op, ia32_am_Dest);
+       }
+
+       return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
 }
 
 
@@ -57,22 +237,23 @@ static ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
 /**
  * Creates an ia32 Add with immediate.
  *
- * @param dbg       firm dbg
- * @param block     the block the new node should belong to
- * @param expr_op   operator
- * @param mode      node mode
- * @return the created ia23 Add_i node
+ * @param env       The transformation environment
+ * @param expr_op   The expression operator
+ * @param const_op  The constant
+ * @return the created ia32 Add node
  */
 static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
-       ir_node *new_op;
-       tarval  *tv         = get_ia32_Immop_tarval(const_op);
-       int      normal_add = 0;
+       ir_node                *new_op     = NULL;
+       tarval                 *tv         = get_ia32_Immop_tarval(const_op);
+       firm_dbg_module_t      *mod        = env->mod;
+       dbg_info               *dbg        = env->dbg;
+       ir_mode                *mode       = env->mode;
+       ir_graph               *irg        = env->irg;
+       ir_node                *block      = env->block;
+       ir_node                *noreg      = be_new_NoReg(irg);
+       ir_node                *nomem      = new_NoMem();
+       int                     normal_add = 1;
        tarval_classification_t class_tv, class_negtv;
-       firm_dbg_module_t *mod   = env->mod;
-       dbg_info          *dbg   = env->dbg;
-       ir_mode           *mode  = env->mode;
-       ir_graph          *irg   = env->irg;
-       ir_node           *block = env->block;
 
        /* const_op: tarval or SymConst? */
        if (tv) {
@@ -82,20 +263,20 @@ static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node
 
                if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */
                        DB((env->mod, LEVEL_2, "Add(1) to Inc ... "));
-                       new_op = new_rd_ia32_Inc(dbg, irg, block, expr_op, mode);
+                       new_op     = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
+                       normal_add = 0;
                }
                else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */
                        DB((mod, LEVEL_2, "Add(-1) to Dec ... "));
-                       new_op = new_rd_ia32_Dec(dbg, irg, block, expr_op, mode);
+                       new_op     = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
+                       normal_add = 0;
                }
-               else
-                       normal_add = 1;
        }
-       else
-               normal_add = 1;
 
-       if (normal_add)
-               new_op = new_rd_ia32_Lea_i(dbg, irg, block, expr_op, mode);
+       if (normal_add) {
+               new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
+               set_ia32_Immop_attr(new_op, const_op);
+       }
 
        return new_op;
 }
@@ -111,128 +292,59 @@ static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node
  * @return the created ia32 Add node
  */
 static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       ir_node *shli_op;
-       ir_node *expr_op;
-       ir_node *new_op;
-       int normal_add  = 0;
-       dbg_info *dbg   = env->dbg;
-       ir_mode  *mode  = env->mode;
-       ir_graph *irg   = env->irg;
-       ir_node  *block = env->block;
+       ir_node  *new_op = NULL;
+       dbg_info *dbg    = env->dbg;
+       ir_mode  *mode   = env->mode;
+       ir_graph *irg    = env->irg;
+       ir_node  *block  = env->block;
+       ir_node  *noreg  = be_new_NoReg(irg);
+       ir_node  *nomem  = new_NoMem();
+       ir_node  *expr_op, *imm_op;
+
+       imm_op  = get_immediate_op(op1, op2);
+       expr_op = get_expr_op(op1, op2);
+
+       assert((expr_op || imm_op) && "invalid operands");
 
        if (mode_is_float(mode)) {
-               return new_rd_ia32_fAdd(dbg, irg, block, op1, op2, mode);
+               return gen_binop(env, op1, op2, new_rd_ia32_fAdd);
        }
-
-       /* try to optimize with LEA */
-
-       shli_op = is_ia32_Shl_i(op1) ? op1 : (is_ia32_Shl_i(op2) ? op2 : NULL);
-       expr_op = shli_op == op1 ? op2 : (shli_op == op2 ? op1 : NULL);
-
-       if (shli_op) {
-               tarval *tv   = get_ia32_Immop_tarval(shli_op);
-               tarval *offs = NULL;
-               if (tv) {
-                       switch (get_tarval_long(tv)) {
-                               case 1:
-                               case 2:
-                               case 3:
-                                       // If the other operand of the LEA is an LEA_i (that means LEA ofs(%regop1)),
-                                       // we can skip it and transform the whole sequence into LEA ofs(%regop1, %regop2, shl_val),
-                                       if (is_ia32_Lea_i(expr_op)) {
-                                               offs    = get_ia32_Immop_tarval(expr_op);
-                                               expr_op = get_irn_n(expr_op, 0);
-                                       }
-
-                                       new_op = new_rd_ia32_Lea(dbg, irg, block, expr_op, get_irn_n(shli_op, 0), mode);
-                                       set_ia32_Immop_tarval(new_op, tv);
-                                       set_ia32_am_offs(new_op, offs);
-
-                                       break;
-                               default:
-                                       normal_add = 1;
-                                       break;
-                       }
+       else {
+               /* integer ADD */
+               if (!expr_op) {
+                       /* No expr_op means, that we have two const - one symconst and */
+                       /* one tarval or another symconst - because this case is not   */
+                       /* covered by constant folding                                 */
+
+                       new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode_T);
+                       add_ia32_am_offs(new_op, get_ia32_cnst(op1));
+                       add_ia32_am_offs(new_op, get_ia32_cnst(op2));
+
+                       /* set AM support */
+                       set_ia32_am_support(new_op, ia32_am_Source);
+                       set_ia32_op_type(new_op, ia32_AddrModeS);
                }
-               else
-                       normal_add = 1;
-       }
-       else
-               normal_add = 1;
-
-       if (normal_add) {
-               new_op = new_rd_ia32_Lea(dbg, irg, block, op1, op2, mode);
-               set_ia32_Immop_tarval(new_op, get_tarval_null(mode_Iu));
-               set_ia32_am_offs(new_op, NULL);
-       }
+               else if (imm_op) {
+                       /* This is expr + const */
+                       new_op = gen_imm_Add(env, expr_op, imm_op);
 
-       return new_op;
-}
-
-
-
-/**
- * Generates an ia32 Mul node.
- *
- * @param env      The transformation environment
- * @param op1      The first faktor
- * @param op2      The second factor
- * @param mul_flav flavour_Mul/Mulh
- * @return The ready-to-go Mul node
- */
-ir_node *generate_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, op_flavour_t mul_flav, int is_imm_op) {
-       ir_node    *in_keep[1], *res;
-       long        pn_good, pn_bad;
-       dbg_info   *dbg   = env->dbg;
-       ir_graph   *irg   = env->irg;
-       ir_node    *block = env->block;
-       ir_mode    *mode  = env->mode;
-       ir_node    *mul;
-
-       /* create the mul */
-       if (is_imm_op) {
-               mul = new_rd_ia32_Mul_i(dbg, irg, block, op1, mode_T);
-               set_ia32_Immop_attr(mul, op2);
-       }
-       else {
-               mul = new_rd_ia32_Mul(dbg, irg, block, op1, op2, mode_T);
-       }
-       set_ia32_flavour(mul, mul_flav);
+                       /* set AM support */
+                       set_ia32_am_support(new_op, ia32_am_Dest);
+               }
+               else {
+                       /* This is a normal add */
+                       new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
 
-       /* create the mul infrastructure */
-       if (mul_flav == flavour_Mul) {
-               pn_good = pn_EAX;
-               pn_bad  = pn_EDX;
-       }
-       else { /* Mulh */
-               pn_good = pn_EDX;
-               pn_bad  = pn_EAX;
+                       /* set AM support */
+                       set_ia32_am_support(new_op, ia32_am_Full);
+               }
        }
 
-       res        = new_rd_Proj(dbg, irg, block, mul, mode, pn_good);
-       in_keep[0] = new_rd_Proj(dbg, irg, block, mul, mode, pn_bad);
-
-       be_new_Keep(&ia32_reg_classes[CLASS_ia32_general_purpose], irg, block, 1, in_keep);
-
-       return res;
+       return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
 }
 
 
 
-/**
- * Creates an ia32 Mul with immediate.
- *
- * @param dbg       firm dbg
- * @param block     the block the new node should belong to
- * @param expr_op   operator
- * @param mode      node mode
- * @return the created ia23 Mul_i node
- */
-static ir_node *gen_imm_Mul(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
-       /* Mul with immediate only possible with int, so we don't need to check for float */
-       return generate_Mul(env, expr_op, const_op, flavour_Mul, 1);
-}
-
 /**
  * Creates an ia32 Mul.
  *
@@ -244,132 +356,114 @@ static ir_node *gen_imm_Mul(ia32_transform_env_t *env, ir_node *expr_op, ir_node
  * @return the created ia32 Mul node
  */
 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)) {
-               return new_rd_ia32_fMul(env->dbg, env->irg, env->block, op1, op2, env->mode);
+               new_op = gen_binop(env, op1, op2, new_rd_ia32_fMul);
        }
        else {
-               return generate_Mul(env, op1, op2, flavour_Mul, 0);
+               new_op = gen_binop(env, op1, op2, new_rd_ia32_Mul);
        }
-}
 
+       return new_op;
+}
 
 
-/**
- * Creates an ia32 Mulh with immediate.
- * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
- * this result while Mul returns the lower 32 bit.
- *
- * @param dbg       firm dbg
- * @param block     the block the new node should belong to
- * @param expr_op   operator
- * @param mode      node mode
- * @return the created ia23 Mulh_i node
- */
-static ir_node *gen_imm_Mulh(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
-       return generate_Mul(env, expr_op, const_op, flavour_Mulh, 1);
-}
 
 /**
  * Creates an ia32 Mulh.
  * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
  * this result while Mul returns the lower 32 bit.
  *
- * @param dbg       firm node dbg
- * @param block     the block the new node should belong to
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
+ * @param env   The transformation environment
+ * @param op1   The first operator
+ * @param op2   The second operator
  * @return the created ia32 Mulh node
  */
 static ir_node *gen_Mulh(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       return generate_Mul(env, op1, op2, flavour_Mulh, 0);
-}
+       ir_node *proj_EAX, *proj_EDX, *mulh;
+       ir_node *in[1];
 
+       assert(mode_is_float(env->mode) && "Mulh with float not supported");
+       proj_EAX = gen_binop(env, op1, op2, new_rd_ia32_Mulh);
+       mulh     = get_Proj_pred(proj_EAX);
+       proj_EDX = new_rd_Proj(env->dbg, env->irg, env->block, mulh, env->mode, pn_EDX);
 
+       /* to be on the save side */
+       set_Proj_proj(proj_EAX, pn_EAX);
 
-/**
- * Creates an ia32 And with immediate.
- *
- * @param dbg       firm dbg
- * @param block     the block the new node should belong to
- * @param expr_op   operator
- * @param mode      node mode
- * @return the created ia23 And_i node
- */
-static ir_node *gen_imm_And(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
-       return new_rd_ia32_And_i(env->dbg, env->irg, env->block, expr_op, env->mode);
+       if (get_ia32_cnst(mulh)) {
+               /* Mulh with const cannot have AM */
+               set_ia32_am_support(mulh, ia32_am_None);
+       }
+       else {
+               /* Mulh cannot have AM for destination */
+               set_ia32_am_support(mulh, ia32_am_Source);
+       }
+
+       in[0] = proj_EAX;
+
+       /* keep EAX */
+       be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, in);
+
+       return proj_EDX;
 }
 
+
+
 /**
  * Creates an ia32 And.
  *
- * @param dbg       firm node dbg
- * @param block     the block the new node should belong to
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
- * @return the created ia32 And node
+ * @param env   The transformation environment
+ * @param op1   The first operator
+ * @param op2   The second operator
+ * @return The created ia32 And node
  */
 static ir_node *gen_And(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       return new_rd_ia32_And(env->dbg, env->irg, env->block, op1, op2, env->mode);
+       if (mode_is_float(env->mode)) {
+               return gen_binop(env, op1, op2, new_rd_ia32_fAnd);
+       }
+       else {
+               return gen_binop(env, op1, op2, new_rd_ia32_And);
+       }
 }
 
 
 
-/**
- * Creates an ia32 Or with immediate.
- *
- * @param dbg       firm dbg
- * @param block     the block the new node should belong to
- * @param expr_op   operator
- * @param mode      node mode
- * @return the created ia23 Or_i node
- */
-static ir_node *gen_imm_Or(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
-       return new_rd_ia32_Or_i(env->dbg, env->irg, env->block, expr_op, env->mode);
-}
-
 /**
  * Creates an ia32 Or.
  *
- * @param dbg       firm node dbg
- * @param block     the block the new node should belong to
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
- * @return the created ia32 Or node
+ * @param env   The transformation environment
+ * @param op1   The first operator
+ * @param op2   The second operator
+ * @return The created ia32 Or node
  */
 static ir_node *gen_Or(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       return new_rd_ia32_Or(env->dbg, env->irg, env->block, op1, op2, env->mode);
+       if (mode_is_float(env->mode)) {
+               return gen_binop(env, op1, op2, new_rd_ia32_fOr);
+       }
+       else {
+               return gen_binop(env, op1, op2, new_rd_ia32_Or);
+       }
 }
 
 
 
-/**
- * Creates an ia32 Eor with immediate.
- *
- * @param dbg       firm dbg
- * @param block     the block the new node should belong to
- * @param expr_op   operator
- * @param mode      node mode
- * @return the created ia23 Eor_i node
- */
-static ir_node *gen_imm_Eor(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
-       return new_rd_ia32_Eor_i(env->dbg, env->irg, env->block, expr_op, env->mode);
-}
-
 /**
  * Creates an ia32 Eor.
  *
- * @param dbg       firm node dbg
- * @param block     the block the new node should belong to
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
- * @return the created ia32 Eor node
+ * @param env   The transformation environment
+ * @param op1   The first operator
+ * @param op2   The second operator
+ * @return The created ia32 Eor node
  */
 static ir_node *gen_Eor(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       return new_rd_ia32_Eor(env->dbg, env->irg, env->block, op1, op2, env->mode);
+       if (mode_is_float(env->mode)) {
+               return gen_binop(env, op1, op2, new_rd_ia32_fEor);
+       }
+       else {
+               return gen_binop(env, op1, op2, new_rd_ia32_Eor);
+       }
 }
 
 
@@ -377,14 +471,23 @@ static ir_node *gen_Eor(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
 /**
  * Creates an ia32 Max.
  *
- * @param dbg       firm dbg
- * @param block     the block the new node should belong to
- * @param expr_op   operator
- * @param mode      node mode
- * @return the created ia23 Max node
+ * @param env      The transformation environment
+ * @param op1      The first operator
+ * @param op2      The second operator
+ * @return the created ia32 Max node
  */
 static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       return new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode);
+       ir_node *new_op;
+
+       if (mode_is_float(env->mode)) {
+               new_op = gen_binop(env, op1, op2, new_rd_ia32_fMax);
+       }
+       else {
+               new_op = new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode);
+               set_ia32_am_support(new_op, ia32_am_None);
+       }
+
+       return new_op;
 }
 
 
@@ -392,14 +495,23 @@ static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
 /**
  * Creates an ia32 Min.
  *
- * @param dbg       firm dbg
- * @param block     the block the new node should belong to
- * @param expr_op   operator
- * @param mode      node mode
- * @return the created ia23 Min node
+ * @param env      The transformation environment
+ * @param op1      The first operator
+ * @param op2      The second operator
+ * @return the created ia32 Min node
  */
 static ir_node *gen_Min(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       return new_rd_ia32_Min(env->dbg, env->irg, env->block, op1, op2, env->mode);
+       ir_node *new_op;
+
+       if (mode_is_float(env->mode)) {
+               new_op = gen_binop(env, op1, op2, new_rd_ia32_fMin);
+       }
+       else {
+               new_op = new_rd_ia32_Min(env->dbg, env->irg, env->block, op1, op2, env->mode);
+               set_ia32_am_support(new_op, ia32_am_None);
+       }
+
+       return new_op;
 }
 
 
@@ -407,22 +519,23 @@ static ir_node *gen_Min(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
 /**
  * Creates an ia32 Sub with immediate.
  *
- * @param dbg       firm dbg
- * @param block     the block the new node should belong to
- * @param expr_op   operator
- * @param mode      node mode
- * @return the created ia23 Sub_i node
+ * @param env   The transformation environment
+ * @param op1   The first operator
+ * @param op2   The second operator
+ * @return The created ia32 Sub node
  */
 static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
-       ir_node *new_op;
-       tarval  *tv        = get_ia32_Immop_tarval(const_op);
-       int     normal_sub = 0;
+       ir_node                *new_op     = NULL;
+       tarval                 *tv         = get_ia32_Immop_tarval(const_op);
+       firm_dbg_module_t      *mod        = env->mod;
+       dbg_info               *dbg        = env->dbg;
+       ir_mode                *mode       = env->mode;
+       ir_graph               *irg        = env->irg;
+       ir_node                *block      = env->block;
+       ir_node                *noreg      = be_new_NoReg(irg);
+       ir_node                *nomem      = new_NoMem();
+       int                     normal_sub = 1;
        tarval_classification_t class_tv, class_negtv;
-       firm_dbg_module_t *mod   = env->mod;
-       dbg_info          *dbg   = env->dbg;
-       ir_mode           *mode  = env->mode;
-       ir_graph          *irg   = env->irg;
-       ir_node           *block = env->block;
 
        /* const_op: tarval or SymConst? */
        if (tv) {
@@ -432,20 +545,20 @@ static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node
 
                if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */
                        DB((mod, LEVEL_2, "Sub(1) to Dec ... "));
-                       new_op = new_rd_ia32_Dec(dbg, irg, block, expr_op, mode);
+                       new_op     = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
+                       normal_sub = 0;
                }
                else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */
                        DB((mod, LEVEL_2, "Sub(-1) to Inc ... "));
-                       new_op = new_rd_ia32_Inc(dbg, irg, block, expr_op, mode);
+                       new_op     = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
+                       normal_sub = 0;
                }
-               else
-                       normal_sub = 1;
        }
-       else
-               normal_sub = 1;
 
-       if (normal_sub)
-               new_op = new_rd_ia32_Sub_i(dbg, irg, block, expr_op, mode);
+       if (normal_sub) {
+               new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
+               set_ia32_Immop_attr(new_op, const_op);
+       }
 
        return new_op;
 }
@@ -453,18 +566,61 @@ static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node
 /**
  * Creates an ia32 Sub.
  *
- * @param dbg       firm node dbg
- * @param block     the block the new node should belong to
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
- * @return the created ia32 Sub node
+ * @param env   The transformation environment
+ * @param op1   The first operator
+ * @param op2   The second operator
+ * @return The created ia32 Sub node
  */
 static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       if (mode_is_float(env->mode)) {
-               return new_rd_ia32_fSub(env->dbg, env->irg, env->block, op1, op2, env->mode);
+       ir_node  *new_op = NULL;
+       dbg_info *dbg    = env->dbg;
+       ir_mode  *mode   = env->mode;
+       ir_graph *irg    = env->irg;
+       ir_node  *block  = env->block;
+       ir_node  *noreg  = be_new_NoReg(irg);
+       ir_node  *nomem  = new_NoMem();
+       ir_node  *expr_op, *imm_op;
+
+       imm_op  = get_immediate_op(NULL, op2);
+       expr_op = get_expr_op(op1, op2);
+
+       assert((expr_op || imm_op) && "invalid operands");
+
+       if (mode_is_float(mode)) {
+               return gen_binop(env, op1, op2, new_rd_ia32_fSub);
        }
-       return new_rd_ia32_Sub(env->dbg, env->irg, env->block, op1, op2, env->mode);
+       else {
+               /* integer SUB */
+               if (!expr_op) {
+                       /* No expr_op means, that we have two const - one symconst and */
+                       /* one tarval or another symconst - because this case is not   */
+                       /* covered by constant folding                                 */
+
+                       new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode);
+                       add_ia32_am_offs(new_op, get_ia32_cnst(op1));
+                       sub_ia32_am_offs(new_op, get_ia32_cnst(op2));
+
+                       /* set AM support */
+                       set_ia32_am_support(new_op, ia32_am_Source);
+                       set_ia32_op_type(new_op, ia32_AddrModeS);
+               }
+               else if (imm_op) {
+                       /* This is expr - const */
+                       new_op = gen_imm_Sub(env, expr_op, imm_op);
+
+                       /* set AM support */
+                       set_ia32_am_support(new_op, ia32_am_Dest);
+               }
+               else {
+                       /* This is a normal sub */
+                       new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
+
+                       /* set AM support */
+                       set_ia32_am_support(new_op, ia32_am_Full);
+               }
+       }
+
+       return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
 }
 
 
@@ -479,7 +635,7 @@ static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
  * @param dm_flav  flavour_Div/Mod/DivMod
  * @return The created ia32 DivMod node
  */
-static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir_node *divisor, op_flavour_t dm_flav) {
+static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir_node *divisor, ia32_op_flavour_t dm_flav) {
        ir_node  *res, *proj;
        ir_node  *edx_node, *cltd;
        ir_node  *in_keep[1];
@@ -506,13 +662,13 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir
 
        if (mode_is_signed(mode)) {
                /* in signed mode, we need to sign extend the dividend */
-               cltd     = new_rd_ia32_Cltd(dbg, irg, block, dividend, mode_T);
+               cltd     = new_rd_ia32_Cdq(dbg, irg, block, dividend, mode_T);
                dividend = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EAX);
                edx_node = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EDX);
        }
        else {
                edx_node = new_rd_ia32_Const(dbg, irg, block, mode_Iu);
-               set_ia32_Const_type(edx_node, asmop_Const);
+               set_ia32_Const_type(edx_node, ia32_Const);
                set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu));
        }
 
@@ -535,7 +691,7 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir
                        in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_div);
                }
 
-               be_new_Keep(&ia32_reg_classes[CLASS_ia32_general_purpose], irg, block, 1, in_keep);
+               be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in_keep);
        }
 
        return res;
@@ -572,102 +728,55 @@ static ir_node *gen_DivMod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2
 /**
  * Creates an ia32 floating Div.
  *
- * @param dbg       firm node dbg
- * @param block     the block the new node should belong to
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
- * @return the created ia32 fDiv node
+ * @param env   The transformation environment
+ * @param op1   The first operator
+ * @param op2   The second operator
+ * @return The created ia32 fDiv node
  */
 static ir_node *gen_Quot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       return new_rd_ia32_fDiv(env->dbg, env->irg, env->block, op1, op2, env->mode);
+       return gen_binop(env, op1, op2, new_rd_ia32_fDiv);
 }
 
 
 
-/**
- * Creates an ia32 Shl with immediate.
- *
- * @param dbg       firm dbg
- * @param block     the block the new node should belong to
- * @param expr_op   operator
- * @param mode      node mode
- * @return the created ia23 Shl_i node
- */
-static ir_node *gen_imm_Shl(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
-       return new_rd_ia32_Shl_i(env->dbg, env->irg, env->block, expr_op, env->mode);
-}
-
 /**
  * Creates an ia32 Shl.
  *
- * @param dbg       firm node dbg
- * @param block     the block the new node should belong to
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
- * @return the created ia32 Shl node
+ * @param env   The transformation environment
+ * @param op1   The first operator
+ * @param op2   The second operator
+ * @return The created ia32 Shl node
  */
 static ir_node *gen_Shl(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       return new_rd_ia32_Shl(env->dbg, env->irg, env->block, op1, op2, env->mode);
+       return gen_shift_binop(env, op1, op2, new_rd_ia32_Shl);
 }
 
 
 
-/**
- * Creates an ia32 Shr with immediate.
- *
- * @param dbg       firm dbg
- * @param block     the block the new node should belong to
- * @param expr_op   operator
- * @param mode      node mode
- * @return the created ia23 Shr_i node
- */
-static ir_node *gen_imm_Shr(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
-       return new_rd_ia32_Shr_i(env->dbg, env->irg, env->block, expr_op, env->mode);
-}
-
 /**
  * Creates an ia32 Shr.
  *
- * @param dbg       firm node dbg
- * @param block     the block the new node should belong to
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
- * @return the created ia32 Shr node
+ * @param env   The transformation environment
+ * @param op1   The first operator
+ * @param op2   The second operator
+ * @return The created ia32 Shr node
  */
 static ir_node *gen_Shr(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       return new_rd_ia32_Shr(env->dbg, env->irg, env->block, op1, op2, env->mode);
+       return gen_shift_binop(env, op1, op2, new_rd_ia32_Shr);
 }
 
 
 
-/**
- * Creates an ia32 Shrs with immediate.
- *
- * @param dbg       firm dbg
- * @param block     the block the new node should belong to
- * @param expr_op   operator
- * @param mode      node mode
- * @return the created ia23 Shrs_i node
- */
-static ir_node *gen_imm_Shrs(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
-       return new_rd_ia32_Shrs_i(env->dbg, env->irg, env->block, expr_op, env->mode);
-}
-
 /**
  * Creates an ia32 Shrs.
  *
- * @param dbg       firm node dbg
- * @param block     the block the new node should belong to
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
- * @return the created ia32 Shrs node
+ * @param env   The transformation environment
+ * @param op1   The first operator
+ * @param op2   The second operator
+ * @return The created ia32 Shrs node
  */
 static ir_node *gen_Shrs(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       return new_rd_ia32_Shrs(env->dbg, env->irg, env->block, op1, op2, env->mode);
+       return gen_shift_binop(env, op1, op2, new_rd_ia32_Shrs);
 }
 
 
@@ -675,15 +784,13 @@ static ir_node *gen_Shrs(ia32_transform_env_t *env, ir_node *op1, ir_node *op2)
 /**
  * Creates an ia32 RotL.
  *
- * @param dbg       firm node dbg
- * @param block     the block the new node should belong to
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
- * @return the created ia32 RotL node
+ * @param env   The transformation environment
+ * @param op1   The first operator
+ * @param op2   The second operator
+ * @return The created ia32 RotL node
  */
 static ir_node *gen_RotL(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       return new_rd_ia32_RotL(env->dbg, env->irg, env->block, op1, op2, env->mode);
+       return gen_shift_binop(env, op1, op2, new_rd_ia32_RotL);
 }
 
 
@@ -693,43 +800,24 @@ static ir_node *gen_RotL(ia32_transform_env_t *env, ir_node *op1, ir_node *op2)
  * NOTE: There is no RotR with immediate because this would always be a RotL
  *       "imm-mode_size_bits" which can be pre-calculated.
  *
- * @param dbg       firm node dbg
- * @param block     the block the new node should belong to
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
- * @return the created ia32 RotR node
+ * @param env   The transformation environment
+ * @param op1   The first operator
+ * @param op2   The second operator
+ * @return The created ia32 RotR node
  */
 static ir_node *gen_RotR(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
-       return new_rd_ia32_RotR(env->dbg, env->irg, env->block, op1, op2, env->mode);
+       return gen_shift_binop(env, op1, op2, new_rd_ia32_RotR);
 }
 
 
 
-/**
- * Transforms a Rot with immediate into an ia32 RotL with immediate
- * as the Firm Rot is a RotL (see NOTE on RotR with immediate above).
- *
- * @param dbg       firm node dbg
- * @param block     the block the new node should belong to
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
- * @return the created ia32 RotL node
- */
-static ir_node *gen_imm_Rot(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
-       return new_rd_ia32_RotL_i(env->dbg, env->irg, env->block, expr_op, env->mode);
-}
-
 /**
  * Creates an ia32 RotR or RotL (depending on the found pattern).
  *
- * @param dbg       firm node dbg
- * @param block     the block the new node should belong to
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
- * @return the created ia32 RotL or RotR node
+ * @param env   The transformation environment
+ * @param op1   The first operator
+ * @param op2   The second operator
+ * @return The created ia32 RotL or RotR node
  */
 static ir_node *gen_Rot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
        ir_node *rotate = NULL;
@@ -738,178 +826,56 @@ static ir_node *gen_Rot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
                 operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
                 that means we can create a RotR instead of an Add and a RotL */
 
-       if (is_ia32_Add_i(op2)) {
-               ir_node *minus = get_irn_n(op2, 0); // is there an op_Minus?
+       if (is_Proj(op2)) {
+               ir_node *pred = get_Proj_pred(op2);
 
-               if (is_ia32_Minus(minus)) {
-                       tarval *tv = get_ia32_Immop_tarval(op2);
-                       long bits  = get_mode_size_bits(env->mode);
+               if (is_ia32_Add(pred)) {
+                       ir_node *pred_pred = get_irn_n(pred, 2);
+                       tarval  *tv        = get_ia32_Immop_tarval(pred);
+                       long     bits      = get_mode_size_bits(env->mode);
 
-                       if (tarval_is_long(tv) && get_tarval_long(tv) == bits) {
-                               DB((env->mod, LEVEL_1, "RotL into RotR ... "));
-                               rotate = gen_RotR(env, op1, get_irn_n(minus, 0));
+                       if (is_Proj(pred_pred)) {
+                               pred_pred = get_Proj_pred(pred_pred);
                        }
-               }
-       }
-
-       if (!rotate)
-               rotate = gen_RotL(env, op1, op2);
-
-       return rotate;
-}
-
-
-
-/**
- * Transforms commutative operations (op_Add, op_And, op_Or, op_Eor)
- * and non-commutative operations with com == 0 (op_Sub, op_Shl, op_Shr, op_Shrs, op_Rot)
- *
- * @param mod       the debug module
- * @param block     the block node belongs to
- * @param node      the node to transform
- * @param op1       first operator
- * @param op2       second operator
- * @param mode      node mode
- * @param com       flag if op is commutative
- * @return the created assembler node
- */
-static ir_node *gen_arith_Op(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, int com) {
-       firm_dbg_module_t *mod      = env->mod;
-       ir_node           *node     = env->irn;
-       ir_node           *imm_op   = NULL;
-       ir_node           *expr_op  = NULL;
-       ir_node           *asm_node = NULL;
-       opcode             opc      = get_irn_opcode(node);
-       ir_op             *op       = get_irn_op(node);
-
-#undef GENOP
-#undef GENOPI
-#undef GENOPI_SETATTR
-#define GENOP(a)          case iro_##a: asm_node = gen_##a(env, op1, op2); break
-#define GENOPI(a)         case iro_##a: asm_node = gen_imm_##a(env, expr_op, imm_op); break
-#define GENOPI_SETATTR(a) case iro_##a: asm_node = gen_imm_##a(env, expr_op, imm_op); set_ia32_Immop_attr(asm_node, imm_op); break
-
-       if (com)
-               imm_op  = get_immediate_op(op1, op2);
-       else
-               imm_op  = get_immediate_op(NULL, op2);
-
-       expr_op = get_expr_op(op1, op2);
 
-       /* TODO: Op(Const, Const) support */
-       if (is_ia32_Const(op1) && is_ia32_Const(op2)) {
-               DB((mod, LEVEL_2, "%+F(Const, Const) -> binop ... ", get_irn_opname(node)));
-               imm_op = NULL;
-       }
-
-       /* There are arithmetic operations which can't take an immediate */
-       switch(opc) {
-               case iro_Div:
-               case iro_Mod:
-               case iro_DivMod:
-                       DB((mod, LEVEL_2, "Div/Mod/DivMod imm -> binop ... "));
-                       imm_op = NULL;
-                       break;
-               default:
-                       if (op == get_op_Min() || op == get_op_Max()) {
-                               DB((mod, LEVEL_2, "MIN/MAX imm -> binop ... "));
-                               imm_op = NULL;
+                       if (is_ia32_Minus(pred_pred) &&
+                               tarval_is_long(tv)       &&
+                               get_tarval_long(tv) == bits)
+                       {
+                               DB((env->mod, LEVEL_1, "RotL into RotR ... "));
+                               rotate = gen_RotR(env, op1, get_irn_n(pred_pred, 2));
                        }
-                       break;
-       }
 
-       DB((mod, LEVEL_1, "(%+F -- %+F) ... ", op1, op2));
-
-       if (!mode_is_float(env->mode) && imm_op) {
-               DB((mod, LEVEL_1, "immop ... "));
-
-               switch(opc) {
-                       GENOPI_SETATTR(Add);
-                       GENOPI(Mul);
-                       GENOPI_SETATTR(And);
-                       GENOPI_SETATTR(Or);
-                       GENOPI_SETATTR(Eor);
-
-                       GENOPI_SETATTR(Sub);
-                       GENOPI_SETATTR(Shl);
-                       GENOPI_SETATTR(Shr);
-                       GENOPI_SETATTR(Shrs);
-                       GENOPI_SETATTR(Rot);
-                       default:
-                               if (op == get_op_Mulh()) {
-                                       asm_node = gen_imm_Mulh(env, expr_op, imm_op);
-                               }
-                               else {
-                                       assert("binop_i: THIS SHOULD NOT HAPPEN");
-                               }
                }
        }
-       else {
-               DB((mod, LEVEL_1, "binop ... "));
-
-               switch(opc) {
-                       GENOP(Add);
-                       GENOP(Mul);
-                       GENOP(And);
-                       GENOP(Or);
-                       GENOP(Eor);
-
-                       GENOP(Quot);
-
-                       GENOP(Div);
-                       GENOP(Mod);
-                       GENOP(DivMod);
-
-                       GENOP(Sub);
-                       GENOP(Shl);
-                       GENOP(Shr);
-                       GENOP(Shrs);
-                       GENOP(Rot);
-                       default:
-                               if (op == get_op_Max()) {
-                                       asm_node = gen_Max(env, op1, op2);
-                               }
-                               else if (op == get_op_Min()) {
-                                       asm_node = gen_Min(env, op1, op2);
-                               }
-                               else if (op == get_op_Mulh()) {
-                                       asm_node = gen_Mulh(env, op1, op2);
-                               }
-                               else {
-                                       assert("binop: THIS SHOULD NOT HAPPEN");
-                               }
-               }
+
+       if (!rotate) {
+               rotate = gen_RotL(env, op1, op2);
        }
 
-       return asm_node;
+       return rotate;
 }
-#undef GENOP
-#undef GENOPI
-#undef GENOPI_SETATTR
 
 
 
 /**
  * Transforms a Minus node.
  *
- * @param mod     the debug module
- * @param block   the block the new node should belong to
- * @param node    the ir Minus node
- * @param op      operator
- * @param mode    node mode
- * @return the created ia32 Minus node
+ * @param env   The transformation environment
+ * @param op    The operator
+ * @return The created ia32 Minus node
  */
 static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) {
-       if (is_ia32_Minus(op) || is_ia32_fMinus(op)) {
-               DB((env->mod, LEVEL_1, "--(e) to e ..."));
-               return get_irn_n(op, 0);
+       ir_node *new_op;
+
+       if (mode_is_float(env->mode)) {
+               assert(0);
        }
        else {
-               if (mode_is_float(env->mode)) {
-                       return new_rd_ia32_fMinus(env->dbg, env->irg, env->block, op, env->mode);
-               }
-               return new_rd_ia32_Minus(env->dbg, env->irg, env->block, op, env->mode);
+               new_op = gen_unop(env, op, new_rd_ia32_Minus);
        }
+
+       return new_op;
 }
 
 
@@ -917,12 +883,9 @@ static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) {
 /**
  * Transforms a Conv node.
  *
- * @param mod     the debug module
- * @param block   the block the new node should belong to
- * @param node    the ir Conv node
- * @param op      operator
- * @param mode    node mode
- * @return the created ia32 Conv node
+ * @param env   The transformation environment
+ * @param op    The operator
+ * @return The created ia32 Conv node
  */
 static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *op) {
        return new_rd_ia32_Conv(env->dbg, env->irg, env->block, op, env->mode);
@@ -933,15 +896,21 @@ static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *op) {
 /**
  * Transforms a Not node.
  *
- * @param mod     the debug module
- * @param block   the block the new node should belong to
- * @param node    the ir Not node
- * @param op      operator
- * @param mode    node mode
- * @return the created ia32 Not node
+ * @param env   The transformation environment
+ * @param op    The operator
+ * @return The created ia32 Not node
  */
 static ir_node *gen_Not(ia32_transform_env_t *env, ir_node *op) {
-       return new_rd_ia32_Not(env->dbg, env->irg, env->block, op, env->mode);
+       ir_node *new_op;
+
+       if (mode_is_float(env->mode)) {
+               assert(0);
+       }
+       else {
+               new_op = gen_unop(env, op, new_rd_ia32_Not);
+       }
+
+       return new_op;
 }
 
 
@@ -949,12 +918,9 @@ static ir_node *gen_Not(ia32_transform_env_t *env, ir_node *op) {
 /**
  * Transforms an Abs node.
  *
- * @param mod     the debug module
- * @param block   the block the new node should belong to
- * @param node    the ir Abs node
- * @param op      operator
- * @param mode    node mode
- * @return the created ia32 Abs node
+ * @param env   The transformation environment
+ * @param op    The operator
+ * @return The created ia32 Abs node
  */
 static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
        ir_node  *res, *p_eax, *p_edx;
@@ -962,12 +928,20 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
        ir_mode  *mode  = env->mode;
        ir_graph *irg   = env->irg;
        ir_node  *block = env->block;
+       ir_node  *noreg = be_new_NoReg(irg);
+       ir_node  *nomem = new_NoMem();
 
-       res   = new_rd_ia32_Cltd(dbg, irg, block, op, mode_T);
+       if (mode_is_float(mode)) {
+               assert(0);
+       }
+
+       res   = new_rd_ia32_Cdq(dbg, irg, block, op, mode_T);
        p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_EAX);
        p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_EDX);
-       res   = new_rd_ia32_Eor(dbg, irg, block, p_eax, p_edx, mode);
-       res   = new_rd_ia32_Sub(dbg, irg, block, res, p_edx, mode);
+       res   = new_rd_ia32_Eor(dbg, irg, block, noreg, noreg, p_eax, p_edx, nomem, mode_T);
+       res   = new_rd_Proj(dbg, irg, block, res, mode, 0);
+       res   = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, res, p_edx, nomem, mode_T);
+       res   = new_rd_Proj(dbg, irg, block, res, mode, 0);
 
        return res;
 }
@@ -984,12 +958,13 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
  * @return the created ia32 Load node
  */
 static ir_node *gen_Load(ia32_transform_env_t *env) {
-       ir_node *node = env->irn;
+       ir_node *node  = env->irn;
+       ir_node *noreg = be_new_NoReg(env->irg);
 
        if (mode_is_float(env->mode)) {
-               return new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
+               return new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
        }
-       return new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
+       return new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
 }
 
 
@@ -1004,12 +979,13 @@ static ir_node *gen_Load(ia32_transform_env_t *env) {
  * @return the created ia32 Store node
  */
 ir_node *gen_Store(ia32_transform_env_t *env) {
-       ir_node *node = env->irn;
+       ir_node *node  = env->irn;
+       ir_node *noreg = be_new_NoReg(env->irg);
 
        if (mode_is_float(env->mode)) {
-               return new_rd_ia32_fStore(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
+               return 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);
        }
-       return new_rd_ia32_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
+       return 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);
 }
 
 
@@ -1028,7 +1004,7 @@ static ir_node *gen_Call(ia32_transform_env_t *env) {
        ir_node          **in;
        ir_node           *new_call, *sync;
        int                i, j, n_new_call_in, ignore = 0;
-       asmop_attr        *attr;
+       ia32_attr_t       *attr;
        dbg_info          *dbg          = env->dbg;
        ir_graph          *irg          = env->irg;
        ir_node           *block        = env->block;
@@ -1124,13 +1100,13 @@ static ir_node *gen_Call(ia32_transform_env_t *env) {
        /* 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_floating_point_xmm0;
+                       attr->out_req[0] = &ia32_default_req_ia32_fp_xmm0;
                else
-                       attr->out_req[0] = &ia32_default_req_ia32_general_purpose_eax;
+                       attr->out_req[0] = &ia32_default_req_ia32_gp_eax;
        }
        else if (n_res == 2) {
-               attr->out_req[0] = &ia32_default_req_ia32_general_purpose_eax;
-               attr->out_req[1] = &ia32_default_req_ia32_general_purpose_edx;
+               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 */
@@ -1144,22 +1120,21 @@ static ir_node *gen_Call(ia32_transform_env_t *env) {
 /**
  * Transforms a Cond -> Proj[b] -> Cmp into a CondJmp or CondJmp_i
  *
- * @param mod     the debug module
- * @param block   the block the new node should belong to
- * @param node    the ir Cond node
- * @param mode    mode of the Cond
+ * @param env   The transformation environment
  * @return The transformed node.
  */
 static ir_node *gen_Cond(ia32_transform_env_t *env) {
-       dbg_info          *dbg      = env->dbg;
-       ir_graph          *irg      = env->irg;
-       ir_node           *block    = env->block;
-       ir_node           *node     = env->irn;
-       ir_node           *sel      = get_Cond_selector(node);
-       ir_mode           *sel_mode = get_irn_mode(sel);
-       ir_node           *res      = NULL;
-       ir_node           *pred     = NULL;
-       ir_node           *cmp_a, *cmp_b, *cnst, *expr;
+       dbg_info *dbg      = env->dbg;
+       ir_graph *irg      = env->irg;
+       ir_node  *block    = env->block;
+       ir_node  *node     = env->irn;
+       ir_node  *sel      = get_Cond_selector(node);
+       ir_mode  *sel_mode = get_irn_mode(sel);
+       ir_node  *res      = NULL;
+       ir_node  *pred     = NULL;
+       ir_node  *noreg    = be_new_NoReg(irg);
+       ir_node  *nomem    = new_NoMem();
+       ir_node  *cmp_a, *cmp_b, *cnst, *expr;
 
        if (is_Proj(sel) && sel_mode == mode_b) {
                pred  = get_Proj_pred(sel);
@@ -1173,17 +1148,17 @@ static ir_node *gen_Cond(ia32_transform_env_t *env) {
                expr = get_expr_op(cmp_a, cmp_b);
 
                if (cnst && expr) {
-                       res = new_rd_ia32_CondJmp_i(dbg, irg, block, expr, mode_T);
+                       res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, expr, noreg, nomem, mode_T);
                        set_ia32_Immop_attr(res, cnst);
                }
                else {
-                       res = new_rd_ia32_CondJmp(dbg, irg, block, cmp_a, cmp_b, mode_T);
+                       res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem, mode_T);
                }
 
                set_ia32_pncode(res, get_Proj_proj(sel));
        }
        else {
-               res = new_rd_ia32_SwitchJmp(dbg, irg, block, sel, mode_T);
+               res = new_rd_ia32_SwitchJmp(dbg, irg, block, noreg, noreg, sel, nomem, mode_T);
                set_ia32_pncode(res, get_Cond_defaultProj(node));
        }
 
@@ -1320,36 +1295,6 @@ static ir_node *gen_Proj(ia32_transform_env_t *env) {
 
 
 
-/**
- * Transforms an Alloc node into either ia32_Alloca or ia32_Malloc.
- */
-static ir_node *gen_Alloc(ia32_transform_env_t *env) {
-       dbg_info *dbg   = env->dbg;
-       ir_graph *irg   = env->irg;
-       ir_node  *block = env->block;
-       ir_node  *irn   = env->irn;
-       ir_mode  *mode  = env->mode;
-       ir_node  *size  = get_Alloc_size(irn);
-       ir_node  *mem   = get_Alloc_mem(irn);
-       ir_node  *res;
-
-       if (get_Alloc_where(irn) == stack_alloc) {
-               if (is_ia32_Const(size)) {
-                       res = new_rd_ia32_Alloca_i(dbg, irg, block, mem, mode);
-                       set_ia32_Immop_attr(res, size);
-               }
-               else {
-                       res = new_rd_ia32_Alloca(dbg, irg, block, size, mem, mode);
-               }
-       }
-       else {
-               assert(0 && "malloc should be already lowered");
-               res = NULL;
-       }
-
-       return res;
-}
-
 /*********************************************************
  *                  _             _      _
  *                 (_)           | |    (_)
@@ -1387,31 +1332,31 @@ void ia32_transform_node(ir_node *node, void *env) {
        tenv.mode     = get_irn_mode(node);
        tenv.cg       = cgenv;
 
-#define UNOP(a)        case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break
-#define BINOP(a)       case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break
-#define BINOP_COM(a)   case iro_##a: asm_node = gen_arith_Op(&tenv, get_##a##_left(node), get_##a##_right(node), 1); break
-#define BINOP_NCOM(a)  case iro_##a: asm_node = gen_arith_Op(&tenv, get_##a##_left(node), get_##a##_right(node), 0); break
-#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 UNOP(a)  case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break
+#define BINOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break
+#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
 
        DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
 
        switch (code) {
-               BINOP_COM(Add);
-               BINOP_COM(Mul);
-               BINOP_COM(And);
-               BINOP_COM(Or);
-               BINOP_COM(Eor);
-
-               BINOP_NCOM(Sub);
-               BINOP_NCOM(Shl);
-               BINOP_NCOM(Shr);
-               BINOP_NCOM(Shrs);
-               BINOP_NCOM(Quot);
-               BINOP_NCOM(Div);
-               BINOP_NCOM(Mod);
-               BINOP_NCOM(DivMod);
+               BINOP(Add);
+               BINOP(Sub);
+               BINOP(Mul);
+               BINOP(And);
+               BINOP(Or);
+               BINOP(Eor);
+
+               BINOP(Shl);
+               BINOP(Shr);
+               BINOP(Shrs);
+
+               BINOP(Quot);
+
+               BINOP(Div);
+               BINOP(Mod);
+               BINOP(DivMod);
 
                UNOP(Minus);
                UNOP(Conv);
@@ -1420,10 +1365,11 @@ void ia32_transform_node(ir_node *node, void *env) {
 
                GEN(Load);
                GEN(Store);
-               GEN(Call);
                GEN(Cond);
+
                GEN(Proj);
-               GEN(Alloc);
+               GEN(Call);
+               IGN(Alloc);
 
                IGN(Block);
                IGN(Start);
@@ -1456,11 +1402,14 @@ void ia32_transform_node(ir_node *node, void *env) {
                BAD(CopyB);
 
                default:
-                       if (get_irn_op(node) == get_op_Max() ||
-                               get_irn_op(node) == get_op_Min() ||
-                               get_irn_op(node) == get_op_Mulh())
-                       {
-                               asm_node = gen_arith_Op(&tenv, get_irn_n(node, 0), get_irn_n(node, 1), 1);
+                       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));
                        }
                        break;
 bad: