fixed indent
authorChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Tue, 13 Dec 2005 15:39:47 +0000 (15:39 +0000)
committerChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Tue, 13 Dec 2005 15:39:47 +0000 (15:39 +0000)
changed backend interface
improved emitter
fixed a lot of bugs

ir/be/ia32/Makefile.in
ir/be/ia32/bearch_ia32.c
ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_emitter.h
ir/be/ia32/ia32_gen_decls.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 70e97eb..03f2358 100644 (file)
@@ -18,10 +18,11 @@ full_dir = $(top_srcdir)/ir/be
 full_dirbe = $(full_dir)/$(FIRMBE_ARCH)
 arch = $(FIRMBE_ARCH)
 
-SOURCES = Makefile.in $(arch)_new_nodes.c $(arch)_new_nodes.h gen_$(arch)_new_nodes.c.inl gen_$(arch)_new_nodes.h.inl \
+SOURCES = Makefile.in $(arch)_new_nodes.c $(arch)_new_nodes.h gen_$(arch)_new_nodes.c.inl gen_$(arch)_new_nodes.h \
                gen_$(arch)_emitter.c gen_$(arch)_emitter.h $(arch)_emitter.c $(arch)_emitter.h \
-               bearch_$(arch).c gen_$(arch)_regalloc_if.h gen_$(arch)_regalloc_if.c.inl \
-               $(arch)_transform.c $(arch)_transform.h $(arch)_gen_decls.c $(arch)_gen_decls.h
+               bearch_$(arch).c gen_$(arch)_regalloc_if_t.h gen_$(arch)_regalloc_if.h gen_$(arch)_regalloc_if.c \
+               $(arch)_transform.c $(arch)_transform.h $(arch)_gen_decls.c $(arch)_gen_decls.h \
+               $(arch)_map_regs.c $(arch)_map_regs.h
 
 include $(topdir)/MakeRules
 
@@ -33,7 +34,7 @@ CPPFLAGS +=   -I$(top_srcdir)/ir/adt   -I$(top_srcdir)/ir/ir  -I$(top_srcdir)/ir/
 
 include $(top_srcdir)/MakeTargets
 
-$(full_dirbe)/$(arch)_new_nodes.c: $(full_dirbe)/gen_$(arch)_new_nodes.c.inl $(full_dirbe)/gen_$(arch)_regalloc_if.c.inl $(full_dirbe)/gen_$(arch)_regalloc_if.h
+$(full_dirbe)/$(arch)_new_nodes.c: $(full_dirbe)/gen_$(arch)_regalloc_if.h $(full_dirbe)/gen_$(arch)_new_nodes.c.inl
 
 $(full_dirbe)/$(arch)_new_nodes.h: $(full_dirbe)/gen_$(arch)_new_nodes.h.inl
 
@@ -45,7 +46,7 @@ $(full_dirbe)/gen_$(arch)_new_nodes.c.inl $(full_dirbe)/gen_$(arch)_new_nodes.h.
 $(full_dirbe)/gen_$(arch)_emitter.c $(full_dirbe)/gen_$(arch)_emitter.h: $(full_dir)/scripts/generate_emitter.pl $(full_dirbe)/$(arch)_spec.pl
        $(full_dir)/scripts/generate_emitter.pl $(full_dirbe)/$(arch)_spec.pl $(full_dirbe)
 
-$(full_dirbe)/gen_$(arch)_regalloc_if.c.inl $(full_dirbe)/gen_$(arch)_regalloc_if.h: $(full_dir)/scripts/generate_regalloc_if.pl $(full_dirbe)/$(arch)_spec.pl
+$(full_dirbe)/gen_$(arch)_regalloc_if.c $(full_dirbe)/gen_$(arch)_regalloc_if.h $(full_dirbe)/gen_$(arch)_regalloc_if_t.h: $(full_dir)/scripts/generate_regalloc_if.pl $(full_dirbe)/$(arch)_spec.pl
        $(full_dir)/scripts/generate_regalloc_if.pl $(full_dirbe)/$(arch)_spec.pl $(full_dirbe)
 
 all: subdir.o
index da45d1b..51a5dfb 100644 (file)
@@ -1,31 +1,71 @@
 #include "pseudo_irg.h"
 #include "irgwalk.h"
+#include "irprog.h"
+#include "irprintf.h"
+#include "bearch_ia32.h"
 
 #include "bitset.h"
 #include "debug.h"
 
+#include <obstack.h>
+
+#ifdef obstack_chunk_alloc
+# undef obstack_chunk_alloc
+# define obstack_chunk_alloc malloc
+#else
+# define obstack_chunk_alloc malloc
+# define obstack_chunk_free free
+#endif
+
 #include "../bearch.h"                /* the general register allocator interface */
 
 #include "ia32_new_nodes.h"           /* ia32 nodes interface */
 #include "gen_ia32_regalloc_if.h"     /* the generated interface (register type and class defenitions) */
 #include "ia32_gen_decls.h"           /* interface declaration emitter */
 #include "ia32_transform.h"
+#include "ia32_emitter.h"
+#include "ia32_map_regs.h"
 
-/* define shorter names for classes and indicees */
+#define DEBUG_MODULE "be.isa.ia32"
 
-#define N_GP_REGS   N_ia32_general_purpose_REGS
-#define N_FP_REGS   N_ia32_floating_point_REGS
-#define N_FLAG_REGS N_ia32_flag_register_REGS
+/* TODO: ugly */
+static set *cur_reg_set = NULL;
 
-#define CLS_GP   CLASS_ia32_general_purpose
-#define CLS_FP   CLASS_ia32_floating_point
-#define CLS_FLAG CLASS_ia32_flag_register
+/**
+ * Stuff needed for dummy register requirements to keep register allocator
+ * happy during development.
+ */
+static arch_register_t       ia32_dummy_regs[500];
+static arch_register_class_t ia32_dummy_reg_class = {
+       "dummy",
+       500,
+       ia32_dummy_regs
+};
+
+static arch_register_req_t ia32_dummy_register_req = {
+       arch_register_req_type_normal,
+       &ia32_dummy_reg_class,
+       { NULL }
+};
 
-#define N_CLASSES (sizeof(ia32_reg_classes) / sizeof(ia32_reg_classes[0]))
 
-extern arch_register_class_t ia32_reg_classes[3];
 
-/* Implementation of the register allocator functions */
+/**************************************************
+ *                         _ _              _  __
+ *                        | | |            (_)/ _|
+ *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
+ * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
+ * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
+ * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
+ *            __/ |
+ *           |___/
+ **************************************************/
+
+static ir_node *my_skip_proj(const ir_node *n) {
+       while (is_Proj(n))
+               n = get_Proj_pred(n);
+       return (ir_node *)n;
+}
 
 /**
  * Return register requirements for an ia32 node.
@@ -33,140 +73,377 @@ extern arch_register_class_t ia32_reg_classes[3];
  * will be asked for this information.
  */
 static const arch_register_req_t *ia32_get_irn_reg_req(const arch_irn_ops_t *self, arch_register_req_t *req, const ir_node *irn, int pos) {
-  const arch_register_req_t **irn_req;
+       const arch_register_req_t **irn_req;
+       long node_pos = pos == -1 ? 0 : pos;
+       ir_mode *mode = get_irn_mode(irn);
+       firm_dbg_module_t *mod = firm_dbg_register(DEBUG_MODULE);
+
+       if (mode == mode_T || mode == mode_M) {
+               DBG((mod, LEVEL_1, "ignoring mode_T, mode_M node %+F\n", irn));
+               return NULL;
+       }
+
+       DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));
+
+       if (is_Proj(irn)) {
+               if (pos == -1)
+                       node_pos = translate_proj_pos(irn);
+               else
+                       node_pos = pos;
+
+               irn = my_skip_proj(irn);
+
+               DBG((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
+       }
+
+       if (is_ia32_irn(irn)) {
+               if (pos >= 0) {
+                       irn_req = get_ia32_in_req(irn);
+               }
+               else {
+                       irn_req = get_ia32_out_req(irn);
+                       pos     = node_pos;
+               }
+
+               DBG((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", irn, pos));
+
+               memcpy(req, irn_req[pos], sizeof(*req));
+               return req;
+       }
+       else {
+               /* treat Phi like Const with default requirements */
+               if (is_Phi(irn)) {
+                       DBG((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
+                       if (mode_is_float(mode))
+                               memcpy(req, &ia32_default_req_ia32_floating_point, sizeof(*req));
+                       else if (mode_is_int(mode) || mode_is_reference(mode))
+                               memcpy(req, &ia32_default_req_ia32_general_purpose, sizeof(*req));
+                       else if (mode == mode_T || mode == mode_M) {
+                               DBG((mod, LEVEL_1, "ignoring Phi node %+F\n", irn));
+                               return NULL;
+                       }
+                       else
+                               assert(0 && "unsupported Phi-Mode");
+               }
+               else if (get_irn_op(irn) == op_Start) {
+                       DBG((mod, LEVEL_1, "returning reqs none for ProjX -> Start (%+F )\n", irn));
+                       switch (node_pos) {
+                               case pn_Start_X_initial_exec:
+                               case pn_Start_P_value_arg_base:
+                               case pn_Start_P_globals:
+                               case pn_Start_P_frame_base:
+                                       memcpy(req, &ia32_default_req_none, sizeof(*req));
+                                       break;
+//                                     memcpy(req, &ia32_default_req_ia32_general_purpose, sizeof(*req));
+//                                     break;
+                               case pn_Start_T_args:
+                                       assert(0 && "ProjT(pn_Start_T_args) should not be asked");
+                       }
+               }
+               else if (get_irn_op(irn) == op_Return && pos >= 0) {
+                       DBG((mod, LEVEL_1, "returning reqs EAX for %+F\n", irn));
+                       memcpy(req, &ia32_default_req_ia32_general_purpose_eax, sizeof(*req));
+               }
+               else {
+                       DBG((mod, LEVEL_1, "returning standard reqs for %+F (not ia32)\n", irn));
+                       memcpy(req, &ia32_dummy_register_req, sizeof(*req));
+               }
+       }
+
+       return req;
+}
 
-  if (is_Proj(irn)) {
-  }
-  else if (is_ia32_irn(irn)) {
-    if (get_irn_mode(irn) == mode_T) {
-      return NULL;
-    }
+static void ia32_set_irn_reg(const arch_irn_ops_t *self, ir_node *irn, const arch_register_t *reg) {
+       int pos = 0;
 
-    if (pos >= 0) {
-      irn_req = get_ia32_in_req(irn);
-    }
-    else {
-      irn_req = get_ia32_out_req(irn);
-      pos     = -1 - pos;
-    }
+       if (is_Proj(irn)) {
+               pos = translate_proj_pos(irn);
+               irn = my_skip_proj(irn);
+       }
 
-    memcpy(req, irn_req[pos], sizeof(*req));
-    return req;
-  }
-  else
-    req = NULL;
+       if (is_ia32_irn(irn)) {
+               const arch_register_t **slots;
 
-  return req;
+               slots      = get_ia32_slots(irn);
+               slots[pos] = reg;
+       }
+       else {
+               ia32_set_firm_reg(self, irn, reg, cur_reg_set);
+       }
 }
 
-static int ia32_get_n_operands(const arch_irn_ops_t *self, const ir_node *irn, int in_out) {
-  if (in_out >= 0)
-    return get_irn_arity(irn);
-  else
-    return get_ia32_n_res(irn);
+static const arch_register_t *ia32_get_irn_reg(const arch_irn_ops_t *self, const ir_node *irn) {
+       int pos = 0;
+       const arch_register_t *reg = NULL;
+
+       if (is_Proj(irn)) {
+               pos = translate_proj_pos(irn);
+               irn = my_skip_proj(irn);
+       }
+
+       if (is_ia32_irn(irn)) {
+               const arch_register_t **slots;
+               slots = get_ia32_slots(irn);
+               reg   = slots[pos];
+       }
+       else {
+               reg = ia32_get_firm_reg(self, irn, cur_reg_set);
+       }
+
+       return reg;
 }
 
-static void ia32_set_irn_reg(const arch_irn_ops_t *self, ir_node *irn, int pos, const arch_register_t *reg) {
-  if (is_ia32_irn(irn)) {
-    const arch_register_t **slots;
+static arch_irn_class_t ia32_classify(const arch_irn_ops_t *self, const ir_node *irn) {
+       irn = my_skip_proj(irn);
+       if (is_cfop(irn))
+               return arch_irn_class_branch;
+       else
+               return arch_irn_class_normal;
+}
 
-    slots      = get_ia32_slots(irn);
-    slots[pos] = reg;
-  }
+static arch_irn_flags_t ia32_get_flags(const arch_irn_ops_t *self, const ir_node *irn) {
+       irn = my_skip_proj(irn);
+       if (is_ia32_irn(irn))
+               return get_ia32_flags(irn);
+       else {
+               ir_printf("don't know flags of %+F\n", irn);
+               return 0;
+       }
 }
 
-static const arch_register_t *ia32_get_irn_reg(const arch_irn_ops_t *self, const ir_node *irn, int pos) {
-  if (is_ia32_irn(irn)) {
-    const arch_register_t **slots;
+/* fill register allocator interface */
+
+static const arch_irn_ops_t ia32_irn_ops = {
+       ia32_get_irn_reg_req,
+       ia32_set_irn_reg,
+       ia32_get_irn_reg,
+       ia32_classify,
+       ia32_get_flags
+};
+
+
+
+/**************************************************
+ *                _                         _  __
+ *               | |                       (_)/ _|
+ *   ___ ___   __| | ___  __ _  ___ _ __    _| |_
+ *  / __/ _ \ / _` |/ _ \/ _` |/ _ \ '_ \  | |  _|
+ * | (_| (_) | (_| |  __/ (_| |  __/ | | | | | |
+ *  \___\___/ \__,_|\___|\__, |\___|_| |_| |_|_|
+ *                        __/ |
+ *                       |___/
+ **************************************************/
+
+typedef struct _ia32_code_gen_t {
+       const arch_code_generator_if_t *impl;    /* implementation */
+       ir_graph                       *irg;     /* current irg */
+       FILE                           *out;     /* output file */
+       set                            *reg_set; /* set to memorize registers for non-ia32 nodes (e.g. phi nodes) */
+       firm_dbg_module_t              *mod;     /* debugging module */
+       int                             emit_decls;
+} ia32_code_gen_t;
 
-    slots = get_ia32_slots(irn);
 
-    return slots[pos];
-  }
-  else
-    return NULL;
+
+/**
+ * Transforms the standard firm graph into
+ * an ia32 firm graph
+ */
+static void ia32_prepare_graph(void *self) {
+       ia32_code_gen_t   *cg  = self;
+
+       if (! is_pseudo_ir_graph(cg->irg))
+               irg_walk_blkwise_graph(cg->irg, NULL, ia32_transform_node, cg->mod);
 }
 
-static arch_irn_class_t ia32_classify(const arch_irn_ops_t *self, const ir_node *irn) {
-  if (is_ia32_irn(irn)) {
-    if (is_ia32_Cmp(irn) || is_ia32_Cmp_i(irn)) // TODO: ia32_Jmp
-      return arch_irn_class_branch;
-    else
-      return arch_irn_class_normal;
-  }
-  else
-    return 0;
+
+
+/**
+ * Dummy functions for hooks we don't need but which must be filled.
+ */
+static void ia32_before_sched(void *self) {
 }
 
-static arch_irn_flags_t ia32_get_flags(const arch_irn_ops_t *self, const ir_node *irn) {
-  if (is_ia32_irn(irn))
-    return get_ia32_flags(irn);
-  else
-    return 0;
+static void ia32_before_ra(void *self) {
 }
 
-/* fill register allocator interface */
 
-static const arch_irn_ops_t ia32_irn_ops = {
-  ia32_get_irn_reg_req,
-  ia32_get_n_operands,
-  ia32_set_irn_reg,
-  ia32_get_irn_reg,
-  ia32_classify,
-  ia32_get_flags
+
+/**
+ * Emits the code, closes the output file and frees
+ * the code generator interface.
+ */
+static void ia32_codegen(void *self) {
+       ia32_code_gen_t *cg = self;
+       ir_graph       *irg = cg->irg;
+       FILE           *out = cg->out;
+
+       if (cg->emit_decls) {
+               ia32_gen_decls(cg->out);
+               cg->emit_decls = 0;
+       }
+
+//     ia32_finish_irg(irg);
+       ia32_gen_routine(out, irg, cur_reg_set);
+
+       cur_reg_set = NULL;
+
+       /* de-allocate code generator */
+       del_set(cg->reg_set);
+       free(self);
+}
+
+static const arch_code_generator_if_t ia32_code_gen_if = {
+       ia32_prepare_graph,
+       ia32_before_sched,   /* before scheduling hook */
+       ia32_before_ra,      /* before register allocation hook */
+       ia32_codegen         /* emit && done */
 };
 
-/* Implementation of the backend isa functions */
 
-static void ia32_init(void) {
-  ia32_register_init();
-  ia32_create_opcodes();
+
+/*****************************************************************
+ *  ____             _                  _   _____  _____
+ * |  _ \           | |                | | |_   _|/ ____|  /\
+ * | |_) | __ _  ___| | _____ _ __   __| |   | | | (___   /  \
+ * |  _ < / _` |/ __| |/ / _ \ '_ \ / _` |   | |  \___ \ / /\ \
+ * | |_) | (_| | (__|   <  __/ | | | (_| |  _| |_ ____) / ____ \
+ * |____/ \__,_|\___|_|\_\___|_| |_|\__,_| |_____|_____/_/    \_\
+ *
+ *****************************************************************/
+
+typedef struct _ia32_isa_t {
+       const arch_isa_if_t *impl;
+       int                  num_codegens;
+       FILE                *output_file;
+} ia32_isa_t;
+
+/**
+ * Initializes the backend ISA and opens the output file.
+ */
+static void *ia32_init(FILE *out) {
+       int i;
+       static struct obstack obst;
+       static int inited    = 0;
+       ia32_isa_t *isa      = malloc(sizeof(*isa));
+
+       isa->impl = &ia32_isa_if;
+
+       if(inited)
+               return NULL;
+
+       inited = 1;
+
+       isa->output_file  = out;
+       isa->num_codegens = 0;
+
+       /* init dummy register requirements */
+       obstack_init(&obst);
+
+       for (i = 0; i < 500; i++) {
+               int n;
+               char buf[5];
+               char *name;
+               arch_register_t *reg = &ia32_dummy_regs[i];
+
+               n = snprintf(buf, sizeof(buf), "d%d", i);
+               name = obstack_copy0(&obst, buf, n);
+
+               reg->name      = name;
+               reg->reg_class = &ia32_dummy_reg_class;
+               reg->index     = i;
+               reg->type      = arch_register_type_none;
+       }
+
+       obstack_free(&obst, NULL);
+
+       ia32_register_init();
+       ia32_create_opcodes();
+
+       return isa;
 }
 
-static int ia32_get_n_reg_class(void) {
-  return N_CLASSES;
+
+
+/**
+ * Closes the output file and frees the ISA structure.
+ */
+static void ia32_done(void *self) {
+       free(self);
 }
 
-static const arch_register_class_t *ia32_get_reg_class(int i) {
-  assert(i >= 0 && i < N_CLASSES && "Invalid ia32 register class requested.");
-  return &ia32_reg_classes[i];
+
+
+static int ia32_get_n_reg_class(const void *self) {
+       return N_CLASSES;
+}
+
+static const arch_register_class_t *ia32_get_reg_class(const void *self, int i) {
+       assert(i >= 0 && i < N_CLASSES && "Invalid ia32 register class requested.");
+       return &ia32_reg_classes[i];
 }
 
 static const arch_irn_ops_t *ia32_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn) {
-  return &ia32_irn_ops;
+       return &ia32_irn_ops;
 }
 
-static void ia32_prepare_graph(ir_graph *irg) {
-  firm_dbg_module_t *dbg = firm_dbg_register("be.transform.ia32");
-  if (! is_pseudo_ir_graph(irg))
-    irg_walk_blkwise_graph(irg, NULL, ia32_transform_node, dbg);
+const arch_irn_handler_t ia32_irn_handler = {
+       ia32_get_irn_ops
+};
+
+const arch_irn_handler_t *ia32_get_irn_handler(const void *self) {
+       return &ia32_irn_handler;
 }
 
-static void ia32_codegen(FILE *out) {
-  ia32_gen_decls(out);
 
-#if 0
-  for (i = 0; i < get_irp_n_irgs(); ++i) {
-    ir_graph *irg = get_irp_irg(i);
-    if (! is_pseudo_ir_graph(irg)) {
-      ia32_finish_irg(irg);
-      ia32_gen_routine(out, irg);
-    }
-  }
-#endif
+
+/**
+ * Initializes the code generator interface.
+ */
+static arch_code_generator_t *ia32_make_code_generator(void *self, ir_graph *irg) {
+       ia32_isa_t      *isa = self;
+       ia32_code_gen_t *cg  = malloc(sizeof(*cg));
+
+       cg->impl       = &ia32_code_gen_if;
+       cg->irg        = irg;
+       cg->reg_set    = new_set(cmp_irn_reg_assoc, 1024);
+       cg->mod        = firm_dbg_register("be.transform.ia32");
+       cg->out        = isa->output_file;
+
+       isa->num_codegens++;
+
+       if (isa->num_codegens > 1)
+               cg->emit_decls = 0;
+       else
+               cg->emit_decls = 1;
+
+       cur_reg_set = cg->reg_set;
+
+       return (arch_code_generator_t *)cg;
 }
 
-const arch_irn_handler_t ia32_irn_handler = {
-  ia32_get_irn_ops
-};
+/**
+ * Returns the default scheduler
+ */
+static const list_sched_selector_t *ia32_get_list_sched_selector(const void *self) {
+       return trivial_selector;
+}
 
-/* fill isa interface */
+#ifdef WITH_LIBCORE
+static void ia32_register_options(lc_opt_entry_t *ent)
+{
+}
+#endif /* WITH_LIBCORE */
 
-const arch_isa_if_t ia32_isa = {
-  ia32_init,
-  ia32_get_n_reg_class,
-  ia32_get_reg_class,
-  ia32_prepare_graph,
-  &ia32_irn_handler,
-  ia32_codegen
+const arch_isa_if_t ia32_isa_if = {
+#ifdef WITH_LIBCORE
+       ia32_register_options,
+#endif
+       ia32_init,
+       ia32_done,
+       ia32_get_n_reg_class,
+       ia32_get_reg_class,
+       ia32_get_irn_handler,
+       ia32_make_code_generator,
+       ia32_get_list_sched_selector
 };
index b5d8c07..3557aa8 100644 (file)
+#include <limits.h>
+
 #include "tv.h"
 #include "iredges.h"
+#include "debug.h"
+#include "irgwalk.h"
+#include "irprintf.h"
+#include "irop_t.h"
+
+#include "../besched.h"
+
 #include "ia32_emitter.h"
+#include "gen_ia32_emitter.h"
 #include "ia32_nodes_attr.h"
 #include "ia32_new_nodes.h"
+#include "ia32_map_regs.h"
+
+#define SNPRINTF_BUF_LEN 128
+
+static set *cur_reg_set = NULL;
 
-#define TARVAL_SNPRINTF_BUF_LEN 1024
 
-const char *get_dest_reg_name(ir_node *n, int num) {
-  return get_ia32_out_reg_name(n, --num);
+/*************************************************************
+ *             _       _    __   _          _
+ *            (_)     | |  / _| | |        | |
+ *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
+ * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
+ * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
+ * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
+ * | |                                       | |
+ * |_|                                       |_|
+ *************************************************************/
+
+/**
+ * Return node's tarval as string.
+ */
+const char *node_const_to_str(ir_node *n) {
+       char   *buf;
+       tarval *tv = get_ia32_Immop_tarval(n);
+
+       if (tv) {
+               buf = malloc(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";
 }
 
-const char *get_source_reg_name(ir_node *n, int num) {
-  return get_ia32_in_reg_name(n, --num);
+/**
+ * Returns node's offset as string.
+ */
+char *node_offset_to_str(ir_node *n) {
+       char   *buf;
+       tarval *tv = get_ia32_offs(n);
+
+       if (tv) {
+               buf = malloc(SNPRINTF_BUF_LEN);
+               tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv);
+               return buf;
+       }
+       else
+               return "";
 }
 
-char *node_const_to_str(ir_node *n) {
-  char *buf = malloc(TARVAL_SNPRINTF_BUF_LEN);
-  tarval_snprintf(buf, TARVAL_SNPRINTF_BUF_LEN, get_ia32_Immop_tarval(n));
-  return buf;
+/* We always pass the ir_node which is a pointer. */
+static int ia32_get_arg_type(const lc_arg_occ_t *occ) {
+       return lc_arg_type_ptr;
 }
 
-char *node_offset_to_str(ir_node *n) {
-  char *buf = malloc(TARVAL_SNPRINTF_BUF_LEN);
-  tarval_snprintf(buf, TARVAL_SNPRINTF_BUF_LEN, get_ia32_offs(n));
-  return buf;
+
+/**
+ * Returns the register at in position pos. If the IN node is not an
+ * ia32 node, we check for phi and proj.
+ */
+static const arch_register_t *get_in_reg(ir_node *irn, int pos) {
+       ir_node                *op;
+       const arch_register_t  *reg = NULL;
+       const arch_register_t **slots;
+
+       assert(get_irn_arity(irn) > pos && "Invalid IN position");
+
+       /* The out register of the operator at position pos is the
+          in register we need. */
+       op = get_irn_n(irn, pos);
+
+       if (is_Proj(op)) {
+               pos = (int)translate_proj_pos(op);
+               while(is_Proj(op))
+                       op = get_Proj_pred(op);
+       }
+
+       if (is_ia32_irn(op)) {
+               /* The operator is an ia32 node: this node has only one out */
+               slots = get_ia32_slots(op);
+               reg   = slots[0];
+       }
+       else {
+               /* The operator is not an ia32 node: check for Phi or Proj */
+               if (is_Phi(op)) {
+                       /* Phi's getting register assigned */
+                       reg  = ia32_get_firm_reg(NULL, op, cur_reg_set);
+                       assert(reg && "No register assigned to Phi node");
+               }
+               else {
+                       assert(0 && "Unsupported node for IN register");
+               }
+       }
+
+       return reg;
+}
+
+/**
+ * Returns the number of the in register at position pos.
+ */
+int get_ia32_in_regnr(ir_node *irn, int pos) {
+       const arch_register_t *reg;
+
+       reg = get_in_reg(irn, pos);
+       assert(reg && "no in register");
+       return reg->index;
+}
+
+/**
+ * Returns the name of the in register at position pos.
+ */
+const char *get_ia32_in_reg_name(ir_node *irn, int pos) {
+       const arch_register_t *reg;
+
+       reg = get_in_reg(irn, pos);
+       assert(reg && "no in register");
+       return reg->name;
+}
+
+/**
+ * Get the register name for a node.
+ */
+static int ia32_get_reg_name(lc_appendable_t *app,
+    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
+{
+       const char *buf;
+       ir_node    *X  = arg->v_ptr;
+       int         nr = occ->width - 1;
+
+       if (!X)
+               return lc_arg_append(app, occ, "(null)", 6);
+
+       if (occ->conversion == 's') {
+               buf = get_ia32_in_reg_name(X, nr);
+       }
+       else { /* 'd' */
+               buf = get_ia32_out_reg_name(X, nr);
+       }
+
+       return lc_arg_append(app, occ, buf, strlen(buf));
 }
 
+/**
+ * Returns the tarval or offset of an ia32 as a string.
+ */
+static int ia32_const_to_str(lc_appendable_t *app,
+    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
+{
+       const char *buf;
+       ir_node    *X = arg->v_ptr;
+
+       if (!X)
+               return lc_arg_append(app, occ, "(null)", 6);
+
+       if (occ->conversion == 'c') {
+               buf = node_const_to_str(X);
+       }
+       else { /* 'o' */
+               buf = node_offset_to_str(X);
+       }
+
+       return lc_arg_append(app, occ, buf, strlen(buf));
+}
+
+/**
+ * Determines the SSE suffix depending on the mode.
+ */
+static int ia32_get_mode_suffix(lc_appendable_t *app,
+    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
+{
+       ir_node *X = arg->v_ptr;
+
+       if (!X)
+               return lc_arg_append(app, occ, "(null)", 6);
+
+       if (get_mode_size_bits(get_irn_mode(X)) == 32)
+               return lc_appendable_chadd(app, 's');
+       else
+               return lc_appendable_chadd(app, 'd');
+}
+
+/**
+ * Return the ia32 printf arg environment.
+ * We use the firm environment with some additional handlers.
+ */
+const lc_arg_env_t *ia32_get_arg_env(void) {
+  static lc_arg_env_t *env = NULL;
+
+  static const lc_arg_handler_t ia32_reg_handler   = { ia32_get_arg_type, ia32_get_reg_name };
+  static const lc_arg_handler_t ia32_const_handler = { ia32_get_arg_type, ia32_const_to_str };
+  static const lc_arg_handler_t ia32_mode_handler  = { ia32_get_arg_type, ia32_get_mode_suffix };
+
+  if(env == NULL) {
+    env = firm_get_arg_env();
+
+    lc_arg_register(env, "ia32:sreg", 's', &ia32_reg_handler);
+    lc_arg_register(env, "ia32:dreg", 'd', &ia32_reg_handler);
+    lc_arg_register(env, "ia32:cnst", 'c', &ia32_const_handler);
+    lc_arg_register(env, "ia32:offs", 'o', &ia32_const_handler);
+    lc_arg_register(env, "ia32:mode", 'm', &ia32_mode_handler);
+  }
+
+  return env;
+}
+
+/**
+ * For 2-address code we need to make sure the first src reg is equal to dest reg.
+ */
 void equalize_dest_src(FILE *F, ir_node *n) {
-  if (get_ia32_out_regnr(n, 0) != get_ia32_in_regnr(n, 0))
-    fprintf(F, "\tmovl %%%s, %%%s\t\t\t/* src -> dest for 2 address code */\n", get_source_reg_name(n, 1), get_dest_reg_name(n, 1));
+       if (get_ia32_in_regnr(n, 0) != get_ia32_out_regnr(n, 0)) {
+               if (get_irn_arity(n) > 1 && get_ia32_in_regnr(n, 1) == get_ia32_out_regnr(n, 0)) {
+                       if (! is_op_commutative(get_irn_op(n))) {
+                               /* we only need to echange for non-commutative ops */
+                               lc_efprintf(ia32_get_arg_env(), F, "\txchg %1s, %2s\t\t\t/* xchg src1 <-> src2 for 2 address code */\n", n, n);
+                       }
+               }
+               else {
+                       lc_efprintf(ia32_get_arg_env(), F, "\tmovl %1s, %1d\t\t\t/* src -> dest for 2 address code */\n", n, n);
+               }
+       }
+}
+
+/*
+ * Add a number to a prefix. This number will not be used a second time.
+ */
+char *get_unique_label(char *buf, size_t buflen, const char *prefix) {
+       static unsigned long id = 0;
+       snprintf(buf, buflen, "%s%lu", prefix, ++id);
+       return buf;
 }
 
 /*
  * coding of conditions
  */
 struct cmp2conditon_t {
-  const char *name;
-  pn_Cmp      num;
+       const char *name;
+       pn_Cmp      num;
 };
 
 /*
@@ -86,28 +302,397 @@ static const struct cmp2conditon_t cmp2condition_u[] = {
 /*
  * returns the condition code
  */
-const char *get_cmp_suffix(int cmp_code, int unsigned_cmp)
+static const char *get_cmp_suffix(int cmp_code, int unsigned_cmp)
 {
-  assert(cmp2condition_s[cmp_code].num == cmp_code);
-  assert(cmp2condition_u[cmp_code].num == cmp_code);
+       assert(cmp2condition_s[cmp_code].num == cmp_code);
+       assert(cmp2condition_u[cmp_code].num == cmp_code);
 
-  return unsigned_cmp ? cmp2condition_u[cmp_code & 7].name : cmp2condition_s[cmp_code & 7].name;
+       return unsigned_cmp ? cmp2condition_u[cmp_code & 7].name : cmp2condition_s[cmp_code & 7].name;
 }
 
-void emit_ia32_Proj_Cond(FILE *F, ir_node *n, ir_node *cond) {
-  ir_node *succ_block = get_edge_src_irn(get_irn_out_edge_first(n));
-  ir_node *sel        = get_Cond_selector(cond);
-  ir_mode *sel_mode   = get_irn_mode(sel);
+/**
+ * Returns the target label for a control flow node.
+ */
+static char *get_cfop_target(const ir_node *irn, char *buf) {
+       ir_node *bl = get_irn_link(irn);
 
-  assert(succ_block && "Target block of Proj_Cond missing!");
+       snprintf(buf, SNPRINTF_BUF_LEN, "BLOCK_%ld", get_irn_node_nr(bl));
+       return buf;
+}
 
-  if (sel_mode == mode_b) { // Boolean condition
-    int label = get_irn_node_nr(succ_block);
-    int nr    = get_Proj_proj(n);
-    fprintf(F, "j%s%s Label%d\t\t\t/* if (%sCond) goto Label */\n",
-          nr == pn_Cond_true ? "" : "n",
-          get_cmp_suffix(get_Proj_proj(sel), mode_is_signed(sel_mode)),
-          label,
-          nr == pn_Cond_true ? "" : "!");
-  }
+/**
+ * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
+ */
+static void finish_CondJmp(FILE *F, ir_node *irn) {
+       const ir_node   *proj;
+       const ir_edge_t *edge;
+       char buf[SNPRINTF_BUF_LEN];
+
+       edge = get_irn_out_edge_first(irn);
+       proj = get_edge_src_irn(edge);
+       assert(is_Proj(proj) && "CondJmp with a non-Proj");
+
+       if (get_Proj_proj(proj) == 1) {
+               fprintf(F, "\tj%s %s\t\t\t/* cmp(a, b) == TRUE */\n",
+                                       get_cmp_suffix(get_ia32_pncode(irn), !mode_is_signed(get_irn_mode(get_irn_n(irn, 0)))),
+                                       get_cfop_target(proj, buf));
+       }
+       else  {
+               fprintf(F, "\tjn%s %s\t\t\t/* cmp(a, b) == FALSE */\n",
+                                       get_cmp_suffix(get_ia32_pncode(irn), !mode_is_signed(get_irn_mode(get_irn_n(irn, 0)))),
+                                       get_cfop_target(proj, buf));
+       }
+
+       edge = get_irn_out_edge_next(irn, edge);
+       if (edge) {
+               proj = get_edge_src_irn(edge);
+               assert(is_Proj(proj) && "CondJmp with a non-Proj");
+               fprintf(F, "\tjmp %s\t\t\t/* otherwise */\n", get_cfop_target(proj, buf));
+       }
+}
+
+/**
+ * Emits code for conditional jump with two variables.
+ */
+static void emit_ia32_CondJmp(ir_node *irn, emit_env_t *env) {
+       FILE *F = env->out;
+
+       lc_efprintf(ia32_get_arg_env(), F, "\tcmp %2s, %1s\t\t\t/* CondJmp(%+F, %+F) */\n", irn, irn,
+                                                                                                                                       get_irn_n(irn, 0), get_irn_n(irn, 1));
+       finish_CondJmp(F, irn);
+}
+
+/**
+ * Emits code for conditional jump with immediate.
+ */
+void emit_ia32_CondJmp_i(ir_node *irn, emit_env_t *env) {
+       FILE *F = env->out;
+
+       lc_efprintf(ia32_get_arg_env(), F, "\tcmp %c, %1s\t\t\t/* CondJmp_i(%+F) */\n", irn, irn, get_irn_n(irn, 0));
+       finish_CondJmp(F, irn);
+}
+
+typedef struct _branch_t {
+       ir_node *target;
+       int      value;
+} branch_t;
+
+typedef struct _jmp_tbl_t {
+       ir_node  *defProj;
+       int       min_value;
+       int       max_value;
+       int       num_branches;
+       char     *label;
+       branch_t *branches;
+} jmp_tbl_t;
+
+/* Compare two variables of type branch_t */
+static int ia32_cmp_branch_t(const void *a, const void *b) {
+       branch_t *b1 = (branch_t *)a;
+       branch_t *b2 = (branch_t *)b;
+
+       if (b1->value <= b2->value)
+               return -1;
+       else
+               return 1;
+}
+
+/**
+ * Emits code for a SwitchJmp (creates a jump table if
+ * possible otherwise a cmp-jmp cascade). Port from
+ * cggg ia32 backend
+ */
+void emit_ia32_SwitchJmp(const ir_node *irn, emit_env_t *emit_env) {
+       unsigned long       interval;
+       char                buf[SNPRINTF_BUF_LEN];
+       int                 last_value, i, pn, do_jmp_tbl = 1;
+       jmp_tbl_t           tbl;
+       ir_node            *proj;
+       const ir_edge_t    *edge;
+       const lc_arg_env_t *env = ia32_get_arg_env();
+       FILE               *F   = emit_env->out;
+
+       /* fill the table structure */
+       tbl.label        = malloc(SNPRINTF_BUF_LEN);
+       tbl.label        = get_unique_label(tbl.label, SNPRINTF_BUF_LEN, "JMPTBL_");
+       tbl.defProj      = NULL;
+       tbl.num_branches = get_irn_n_edges(irn);
+       tbl.branches     = calloc(tbl.num_branches, sizeof(*(tbl.branches)));
+       tbl.min_value    = INT_MAX;
+       tbl.max_value    = INT_MIN;
+
+       i = 0;
+       /* go over all proj's and collect them */
+       foreach_out_edge(irn, edge) {
+               proj = get_edge_src_irn(edge);
+               assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
+
+               pn = get_Proj_proj(proj);
+
+               /* create branch entry */
+               tbl.branches[i].target = proj;
+               tbl.branches[i].value  = pn;
+
+               tbl.min_value = pn < tbl.min_value ? pn : tbl.min_value;
+               tbl.max_value = pn > tbl.max_value ? pn : tbl.max_value;
+
+               /* check for default proj */
+               if (pn == get_ia32_pncode(irn)) {
+                       assert(tbl.defProj == NULL && "found two defProjs at SwitchJmp");
+                       tbl.defProj = proj;
+               }
+
+               i++;
+       }
+
+       /* sort the branches by their number */
+       qsort(tbl.branches, tbl.num_branches, sizeof(*(tbl.branches)), ia32_cmp_branch_t);
+
+       /* two-complement's magic make this work without overflow */
+       interval = tbl.max_value - tbl.min_value;
+
+       /* check value interval */
+       if (interval > 16 * 1024) {
+               do_jmp_tbl = 0;
+       }
+
+       /* check ratio of value interval to number of branches */
+       if ((float)(interval + 1) / (float)tbl.num_branches > 8.0) {
+               do_jmp_tbl = 0;
+       }
+
+       if (do_jmp_tbl) {
+               /* emit the table */
+               if (tbl.min_value != 0) {
+                       fprintf(F, "\tcmpl %lu, -%d", interval, tbl.min_value);
+                       lc_efprintf(env, F, "(%1s)\t\t/* first switch value is not 0 */\n", irn);
+               }
+               else {
+                       fprintf(F, "\tcmpl %lu, ", interval);
+                       lc_efprintf(env, F, "%1s\t\t\t/* compare for switch */\n", irn);
+               }
+
+               fprintf(F, "\tja %s\t\t\t/* default jump if out of range  */\n", get_cfop_target(tbl.defProj, buf));
+
+               if (tbl.num_branches > 1) {
+                       /* create table */
+
+                       fprintf(F, "\tjmp *%s", tbl.label);
+                       lc_efprintf(env, F, "(,%1s,4)\t\t/* get jump table entry as target */\n", irn);
+
+                       fprintf(F, "\t.section\t.rodata\t\t/* start jump table */\n");
+                       fprintf(F, "\t.align 4\n");
+
+                       fprintf(F, "%s:\n", tbl.label);
+                       fprintf(F, "\t.long %s\t\t\t/* case %d */\n", get_cfop_target(tbl.branches[0].target, buf), tbl.branches[0].value);
+
+                       last_value = tbl.branches[0].value;
+                       for (i = 1; i < tbl.num_branches; ++i) {
+                               while (++last_value < tbl.branches[i].value) {
+                                       fprintf(F, "\t.long %s\t\t/* default case */\n", get_cfop_target(tbl.defProj, buf));
+                               }
+                               fprintf(F, "\t.long %s\t\t\t/* case %d */\n", get_cfop_target(tbl.branches[i].target, buf), last_value);
+                       }
+
+                       fprintf(F, "\t.text\t\t\t\t/* end of jump table */\n");
+               }
+               else {
+                       /* one jump is enough */
+                       fprintf(F, "\tjmp %s\t\t/* only one case given */\n", get_cfop_target(tbl.branches[0].target, buf));
+               }
+       }
+       else { // no jump table
+               for (i = 0; i < tbl.num_branches; ++i) {
+                       fprintf(F, "\tcmpl %d, ", tbl.branches[i].value);
+                       lc_efprintf(env, F, "%1s", irn);
+                       fprintf(F, "\t\t\t/* case %d */\n", tbl.branches[i].value);
+                       fprintf(F, "\tje %s\n", get_cfop_target(tbl.branches[i].target, buf));
+               }
+
+               fprintf(F, "\tjmp %s\t\t\t/* default case */\n", get_cfop_target(tbl.defProj, buf));
+       }
+
+       if (tbl.branches)
+               free(tbl.branches);
+}
+
+/**
+ * Emits code for a unconditional jump.
+ */
+void emit_Jmp(ir_node *irn, emit_env_t *env) {
+       FILE *F = env->out;
+
+       char buf[SNPRINTF_BUF_LEN];
+       ir_fprintf(F, "\tjmp %s\t\t\t/* Jmp(%+F) */\n", get_cfop_target(irn, buf), get_irn_link(irn));
+}
+
+/**
+ * Emits code for a proj -> node
+ */
+void emit_Proj(ir_node *irn, emit_env_t *env) {
+       ir_node *pred = get_Proj_pred(irn);
+
+       if (get_irn_opcode(pred) == iro_Start) {
+               switch(get_Proj_proj(irn)) {
+                       case pn_Start_X_initial_exec:
+                               emit_Jmp(irn, env);
+                               break;
+                       default:
+                               break;
+               }
+       }
+}
+
+/**
+ * Main emitting function
+ */
+void ia32_emit_node(ir_node *irn, void *env) {
+       emit_env_t *emit_env   = env;
+       firm_dbg_module_t *mod = emit_env->mod;
+       FILE              *F   = emit_env->out;
+
+       DBG((mod, LEVEL_1, "emitting code for %+F\n", irn));
+
+#define IA32_EMIT(a) if (is_ia32_##a(irn))               { emit_ia32_##a(irn, emit_env); return; }
+#define EMIT(a)      if (get_irn_opcode(irn) == iro_##a) { emit_##a(irn, emit_env); return; }
+
+       /* generated int emitter functions */
+       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);
+
+       IA32_EMIT(Max);
+       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(Mulh);
+       IA32_EMIT(Mulh_i);
+
+       IA32_EMIT(Cltd);
+       IA32_EMIT(DivMod);
+
+       IA32_EMIT(Store);
+       IA32_EMIT(Load);
+
+       /* generated floating point emitter */
+       IA32_EMIT(fConst);
+
+       IA32_EMIT(fAdd);
+       IA32_EMIT(fSub);
+       IA32_EMIT(fMinus);
+
+       IA32_EMIT(fMul);
+       IA32_EMIT(fDiv);
+
+       IA32_EMIT(fMin);
+       IA32_EMIT(fMax);
+
+       IA32_EMIT(fLoad);
+       IA32_EMIT(fStore);
+
+       /* other emitter functions */
+       IA32_EMIT(CondJmp);
+       IA32_EMIT(CondJmp_i);
+       IA32_EMIT(SwitchJmp);
+
+       EMIT(Jmp);
+       EMIT(Proj);
+
+       ir_fprintf(F, "\t\t\t\t\t/* %+F */\n", irn);
+}
+
+/**
+ * Walks over the nodes in a block connected by scheduling edges
+ * and emits code for each node.
+ */
+void ia32_gen_block(ir_node *block, void *env) {
+       ir_node *irn;
+
+       fprintf(((emit_env_t *)env)->out, "BLOCK_%ld:\n", get_irn_node_nr(block));
+       sched_foreach(block, irn) {
+               ia32_emit_node(irn, env);
+       }
+}
+
+
+/**
+ * Emits code for function start.
+ */
+void ia32_emit_start(FILE *F, ir_graph *irg) {
+       const char *irg_name = get_entity_name(get_irg_entity(irg));
+
+       fprintf(F, "\t.text\n");
+       fprintf(F, ".globl %s\n", irg_name);
+       fprintf(F, "\t.type\t%s, @function\n", irg_name);
+       fprintf(F, "%s:\n", irg_name);
+}
+
+/**
+ * Emits code for function end
+ */
+void ia32_emit_end(FILE *F, ir_graph *irg) {
+       const char *irg_name = get_entity_name(get_irg_entity(irg));
+
+       fprintf(F, "\tret\n");
+       fprintf(F, "\t.size\t%s, .-%s\n\n", irg_name, irg_name);
+}
+
+/**
+ * Sets labels for control flow nodes (jump target)
+ * TODO: Jump optimization
+ */
+void ia32_gen_labels(ir_node *block, void *env) {
+       ir_node *pred;
+       int n = get_Block_n_cfgpreds(block);
+
+       for (n--; n >= 0; n--) {
+               pred = get_Block_cfgpred(block, n);
+               set_irn_link(pred, block);
+       }
+}
+
+/**
+ * Main driver
+ */
+void ia32_gen_routine(FILE *F, ir_graph *irg, set *reg_set) {
+       emit_env_t emit_env;
+
+       emit_env.mod     = firm_dbg_register("be.codegen.ia32");
+       emit_env.out     = F;
+       emit_env.reg_set = reg_set;
+
+       cur_reg_set = reg_set;
+
+       ia32_emit_start(F, irg);
+       irg_block_walk_graph(irg, ia32_gen_labels, NULL, &emit_env);
+       irg_block_walk_graph(irg, NULL, ia32_gen_block, &emit_env);
+       ia32_emit_end(F, irg);
 }
index a029c3e..4245b4c 100644 (file)
@@ -1,16 +1,25 @@
 #ifndef _IA32_EMITTER_H_
 #define _IA32_EMITTER_H_
 
+#include "irargs_t.h"  // this also inlucdes <libcore/lc_print.h>
 #include "irnode.h"
+#include "set.h"
 
-const char *get_dest_reg_name(ir_node *n, int num);
+#include "debug.h"
 
-const char *get_source_reg_name(ir_node *n, int num);
+typedef struct _emit_env_t {
+       firm_dbg_module_t *mod;
+       FILE *out;
+       set *reg_set;
+} emit_env_t;
 
-char *node_const_to_str(ir_node *n);
-
-char *node_offset_to_str(ir_node *n);
+const lc_arg_env_t *ia32_get_arg_env(void);
 
 void equalize_dest_src(FILE *F, ir_node *n);
 
+int get_ia32_in_regnr(ir_node *irn, int pos);
+const char *get_ia32_in_reg_name(ir_node *irn, int pos);
+
+void ia32_gen_routine(FILE *F, ir_graph *irg, set *reg_set);
+
 #endif /* _IA32_EMITTER_H_ */
index 5390a33..8ec8024 100644 (file)
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#include <assert.h>
 
 #include <obstack.h>
 
index 481d536..19a6fc0 100644 (file)
@@ -17,6 +17,7 @@
 #include "irmode_t.h"
 #include "ircons_t.h"
 #include "iropt_t.h"
+#include "irop.h"
 #include "firm_common_t.h"
 #include "irvrfy_t.h"
 
@@ -24,6 +25,7 @@
 
 #include "ia32_nodes_attr.h"
 #include "ia32_new_nodes.h"
+#include "gen_ia32_regalloc_if.h"
 
 
 
@@ -73,6 +75,8 @@ const char *get_sc_name(ir_node *symc) {
     default:
       assert(0 && "Unsupported SymConst");
   }
+
+  return NULL;
 }
 
 /**
@@ -117,7 +121,7 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
     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)) {
+      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);
@@ -126,7 +130,7 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
         }
       }
       else if (is_ia32_Call(n)) {
-        ir_node *sc = get_ia32_old_ir(get_ia32_old_ir(n));
+        ir_node *sc = get_ia32_old_ir(n);
 
         fprintf(F, "&%s ", get_sc_name(sc));
       }
@@ -248,11 +252,17 @@ 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);
 
-  assert(is_ia32_Const(cnst) && "Need ia32_Const to set Immop attr");
+  assert((is_ia32_Const(cnst) || is_ia32_fConst(cnst)) && "Need ia32_Const to set Immop attr");
 
   na->tp     = ca->tp;
   na->tv     = ca->tv;
-  na->old_ir = ca->old_ir;
+
+  if (ca->old_ir) {
+    na->old_ir = calloc(1, sizeof(*(ca->old_ir)));
+    memcpy(na->old_ir, ca->old_ir, sizeof(*(ca->old_ir)));
+  }
+  else
+    na->old_ir = NULL;
 }
 
 /**
@@ -261,7 +271,7 @@ void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) {
 void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
   asmop_attr *attr = get_ia32_attr(ia32_cnst);
 
-  assert(is_ia32_Const(ia32_cnst) && "Need ia32_Const to set Const attr");
+  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:
@@ -285,136 +295,153 @@ void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
  * Sets the type of an ia32_Const.
  */
 void set_ia32_Const_type(ir_node *node, int type) {
-  asmop_attr *attr   = get_ia32_attr(node);
+       asmop_attr *attr   = get_ia32_attr(node);
 
-  assert(is_ia32_Const(node) && "Need ia32_Const to set type");
-  assert((type == asmop_Const || type == asmop_SymConst) && "Unsupported ia32_Const type");
+       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");
 
-  attr->tp = type;
+       attr->tp = type;
 }
 
 /**
  * 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);
+       asmop_attr *attr = get_ia32_attr(node);
 
-  attr->tp = asmop_Const;
-  attr->tv = tv;
+       attr->tp = asmop_Const;
+       attr->tv = tv;
 }
 
 /**
  * Sets the offset for a Lea.
  */
 void set_ia32_offs(ir_node *node, tarval *offs) {
-  asmop_attr *attr = get_ia32_attr(node);
-  attr->offset     = offs;
+       asmop_attr *attr = get_ia32_attr(node);
+       attr->offset     = offs;
 }
 
 /**
  * Gets the offset for a Lea.
  */
 tarval *get_ia32_offs(const ir_node *node) {
-  asmop_attr *attr = get_ia32_attr(node);
-  return attr->offset;
+       asmop_attr *attr = get_ia32_attr(node);
+       return attr->offset;
 }
 
 /**
  * Returns the argument register requirements of an ia32 node.
  */
 const arch_register_req_t **get_ia32_in_req(const ir_node *node) {
-  asmop_attr *attr = get_ia32_attr(node);
-  return attr->in_req;
+       asmop_attr *attr = get_ia32_attr(node);
+       return attr->in_req;
 }
 
 /**
  * Returns the result register requirements of an ia32 node.
  */
 const arch_register_req_t **get_ia32_out_req(const ir_node *node) {
-  asmop_attr *attr = get_ia32_attr(node);
-  return attr->out_req;
+       asmop_attr *attr = get_ia32_attr(node);
+       return attr->out_req;
 }
 
 /**
- * Returns the register flag of an ia32 node.
+ * Sets the OUT register requirements at position pos.
  */
-arch_irn_flags_t get_ia32_flags(const ir_node *node) {
-  asmop_attr *attr = get_ia32_attr(node);
-  return attr->flags;
+void set_ia32_regreq_out(ir_node *node, const arch_register_req_t *req, int pos) {
+       asmop_attr *attr   = get_ia32_attr(node);
+       attr->out_req[pos] = req;
 }
 
 /**
- * Returns the result register slots of an ia32 node.
+ * Sets the IN register requirements at position pos.
  */
-const arch_register_t **get_ia32_slots(const ir_node *node) {
-  asmop_attr *attr = get_ia32_attr(node);
-  return attr->slots;
+void set_ia32_regreq_in(ir_node *node, const arch_register_req_t *req, int pos) {
+       asmop_attr *attr  = get_ia32_attr(node);
+       attr->in_req[pos] = req;
 }
 
 /**
- * Returns the name of the IN register at position pos.
+ * Returns the register flag of an ia32 node.
  */
-const char *get_ia32_in_reg_name(const ir_node *node, int pos) {
-  assert(0 && "in reg name not yet implemented");
+arch_irn_flags_t get_ia32_flags(const ir_node *node) {
+       asmop_attr *attr = get_ia32_attr(node);
+       return attr->flags;
 }
 
 /**
- * Returns the name of the OUT register at position pos.
+ * Returns the result register slots of an ia32 node.
  */
-const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
-  asmop_attr *attr = get_ia32_attr(node);
-
-  assert(is_ia32_irn(node) && "Not an ia32 node.");
-  assert(pos < attr->n_res && "Invalid OUT position.");
-
-  return attr->slots[pos]->name;
+const arch_register_t **get_ia32_slots(const ir_node *node) {
+       asmop_attr *attr = get_ia32_attr(node);
+       return attr->slots;
 }
 
 /**
- * Returns the index of the IN register at position pos within its register class.
+ * Returns the name of the OUT register at position pos.
  */
-int get_ia32_in_regnr(const ir_node *node, int pos) {
-  assert(0 && "in reg nr not yet implemented");
+const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
+       asmop_attr *attr = get_ia32_attr(node);
+
+       assert(is_ia32_irn(node) && "Not an ia32 node.");
+       assert(pos < attr->n_res && "Invalid OUT position.");
+       assert(attr->slots[pos]  && "No register assigned");
+
+       return attr->slots[pos]->name;
 }
 
 /**
  * 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);
+       asmop_attr *attr = get_ia32_attr(node);
 
-  assert(is_ia32_irn(node) && "Not an ia32 node.");
-  assert(pos < attr->n_res && "Invalid OUT position.");
+       assert(is_ia32_irn(node) && "Not an ia32 node.");
+       assert(pos < attr->n_res && "Invalid OUT position.");
+       assert(attr->slots[pos]  && "No register assigned");
 
-  return attr->slots[pos]->index;
+       return attr->slots[pos]->index;
 }
 
 /**
  * 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;
+       asmop_attr *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);
-  return attr->n_res;
+       asmop_attr *attr = get_ia32_attr(node);
+       return attr->n_res;
 }
 
 /**
  * Sets the flavour of an ia32 DivMod node to flavour_Div/Mod/DivMod.
  */
 void set_ia32_DivMod_flavour(ir_node *node, divmod_flavour_t dm_flav) {
-  asmop_attr *attr = get_ia32_attr(node);
-  attr->dm_flav    = dm_flav;
+       asmop_attr *attr = get_ia32_attr(node);
+       attr->dm_flav    = dm_flav;
 }
 
-/* include generated register allocator interface */
-#include "gen_ia32_regalloc_if.c.inl"
+/**
+ * Returns the projnum code.
+ */
+long get_ia32_pncode(const ir_node *node) {
+       asmop_attr *attr = get_ia32_attr(node);
+       return attr->pn_code;
+}
+
+/**
+ * Sets the projnum code
+ */
+void set_ia32_pncode(ir_node *node, long code) {
+       asmop_attr *attr = get_ia32_attr(node);
+       attr->pn_code = code;
+}
 
 /* Include the generated functions */
 #include "gen_ia32_new_nodes.c.inl"
index 58a73d2..5e44f7d 100644 (file)
@@ -13,6 +13,8 @@ asmop_attr *get_ia32_attr(const ir_node *node);
 
 ir_node *get_ia32_old_ir(const ir_node *node);
 
+const char *get_sc_name(ir_node *symc);
+
 void    set_ia32_Immop_attr(ir_node *node, ir_node *imm);
 tarval *get_ia32_Immop_tarval(const ir_node *node);
 void    set_ia32_Immop_tarval(ir_node *node, tarval *tv);
@@ -20,6 +22,9 @@ void    set_ia32_Immop_tarval(ir_node *node, tarval *tv);
 void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst);
 void set_ia32_Const_type(ir_node *node, int type);
 
+void set_ia32_pncode(ir_node *node, long code);
+long get_ia32_pncode(const ir_node *node);
+
 void    set_ia32_offs(ir_node *node, tarval *offs);
 tarval *get_ia32_offs(const ir_node *node);
 void    set_ia32_n_res(ir_node *node, int n_res);
@@ -32,15 +37,15 @@ const arch_register_req_t **get_ia32_in_req(const ir_node *node);
 const arch_register_req_t **get_ia32_out_req(const ir_node *node);
 const arch_register_t     **get_ia32_slots(const ir_node *node);
 
-const char *get_ia32_in_reg_name(const ir_node *node, int pos);
-const char *get_ia32_out_reg_name(const ir_node *node, int pos);
+void set_ia32_regreq_out(ir_node *node, const arch_register_req_t *req, int pos);
+void set_ia32_regreq_in(ir_node *node, const arch_register_req_t *req, int pos);
 
-int get_ia32_in_regnr(const ir_node *node, int pos);
-int get_ia32_out_regnr(const ir_node *node, int pos);
+const char *get_ia32_out_reg_name(const ir_node *node, int pos);
+int         get_ia32_out_regnr(const ir_node *node, int pos);
 
 int is_ia32_irn(const ir_node *node);
 
 /* Inlcude the generated headers */
-#include "gen_ia32_new_nodes.h.inl"
+#include "gen_ia32_new_nodes.h"
 
 #endif /* _IA32_NEW_NODES_H_ */
index e89b4a6..70013ce 100644 (file)
@@ -16,6 +16,9 @@ typedef struct {
 
   divmod_flavour_t dm_flav;   /**<< flavour of a DivMod (flavour_Div/Mod/DivMod) */
 
+  long pn_code;                        /**<< projnum "types" (e.g. indicates the compare operator of a conditional jump
+                          or an argument number) */
+
   unsigned n_res;      /**<< number of results */
 
   arch_irn_flags_t    flags;     /**<< indicating if spillable and/or rematerializeable */
index ffb1d39..1d43739 100644 (file)
@@ -108,7 +108,16 @@ $arch = "ia32";
 
 %nodes = (
 
-# arithmetic operations
+#-----------------------------------------------------------------#
+#  _       _                                         _            #
+# (_)     | |                                       | |           #
+#  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
+# | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
+# | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
+# |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
+#                   __/ |                                         #
+#                  |___/                                          #
+#-----------------------------------------------------------------#
 
 # commutative operations
 
@@ -119,7 +128,7 @@ $arch = "ia32";
   "comment"     => "construct Add: Add(a, b) = Add(b, a) = a + b",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. addl %s2, %d1\t\t\t/* Add(%s1, %s2) -> %d1 */'
+  "emit"        => '. addl %s2, %d1\t\t\t/* Add(%s1, %s2) -> %d1, (%a1, %a2) */'
 },
 
 "Add_i" => {
@@ -128,7 +137,7 @@ $arch = "ia32";
   "comment"     => "construct Add: Add(a, const) = Add(const, a) = a + const",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. addl %c, %d1\t\t\t/* Add(%c, %s1) -> %d1 */'
+  "emit"        => '. addl %c, %d1\t\t\t/* Add(%c, %s1) -> %d1, (%a1, const) */'
 },
 
 "Mul" => {
@@ -138,10 +147,10 @@ $arch = "ia32";
   "reg_req"     => { "in" => [ "eax", "general_purpose" ], "out" => [ "eax" ] },
   "emit"        =>
 '  if (mode_is_signed(get_irn_mode(n))) {
-4. imull %s2\t\t\t/* signed Mul(%s1, %s2) -> %d1 */
+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 */
+4. mull %s2\t\t\t/* unsigned Mul(%s1, %s2) -> %d1, (%a1, %a2) */
   }
 '
 },
@@ -150,14 +159,13 @@ $arch = "ia32";
   "state"       => "pinned",
   "arity"       => 1,
   "comment"     => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
-#  "reg_req"     => { "in" => [ "eax" ], "out" => [ "eax" ] },
-  "reg_req"     => { "in" => [ "!eax" ], "out" => [ "eax" ] },
+  "reg_req"     => { "in" => [ "eax" ], "out" => [ "eax" ] },
   "emit"        =>
 '  if (mode_is_signed(get_irn_mode(n))) {
-4. imull %c\t\t\t/* signed Mul(%c, %s1) -> %d1 */
+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 */
+4. mull %c\t\t\t/* unsigned Mul(%c, %s1) -> %d1, (%a1, const) */
   }
 '
 },
@@ -169,10 +177,10 @@ $arch = "ia32";
   "reg_req"     => { "in" => [ "eax", "general_purpose" ], "out" => [ "edx" ] },
   "emit"        =>
 '  if (mode_is_signed(get_irn_mode(n))) {
-4. imull %s2\t\t\t/* signed Mulh(%s1, %s2) -> %d1 */
+4. imull %s2\t\t\t/* signed Mulh(%s1, %s2) -> %d1, (%a1, %a2) */
   }
   else {
-4. mull %s2\t\t\t/* unsigned Mulh(%s1, %s2) -> %d1 */
+4. mull %s2\t\t\t/* unsigned Mulh(%s1, %s2) -> %d1, (%a1, %a2) */
   }
 '
 },
@@ -184,10 +192,10 @@ $arch = "ia32";
   "reg_req"     => { "in" => [ "eax" ], "out" => [ "edx" ] },
   "emit"        =>
 '  if (mode_is_signed(get_irn_mode(n))) {
-4. imull %c\t\t\t/* signed Mulh(%c, %s1) -> %d1 */
+4. imull %c\t\t\t/* signed Mulh(%c, %s1) -> %d1, (%a1, const) */
   }
   else {
-4. mull %c\t\t\t/* unsigned Mulh(%c, %s1) -> %d1 */
+4. mull %c\t\t\t/* unsigned Mulh(%c, %s1) -> %d1, (%a1, const) */
   }
 '
 },
@@ -199,7 +207,7 @@ $arch = "ia32";
   "comment"     => "construct And: And(a, b) = And(b, a) = a AND b",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. andl %s2, %d1\t\t\t/* And(%s1, %s2) -> %d1 */'
+  "emit"        => '. andl %s2, %d1\t\t\t/* And(%s1, %s2) -> %d1, (%a1, %a2) */'
 },
 
 "And_i" => {
@@ -208,7 +216,7 @@ $arch = "ia32";
   "comment"     => "construct And: And(a, const) = And(const, a) = a AND const",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. andl %c, %d1\t\t\t/* And(%c, %s1) -> %d1 */'
+  "emit"        => '. andl %c, %d1\t\t\t/* And(%c, %s1) -> %d1, (%a1, const) */'
 },
 
 "Or" => {
@@ -218,7 +226,7 @@ $arch = "ia32";
   "comment"     => "construct Or: Or(a, b) = Or(b, a) = a OR b",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. orl %s2, %d1\t\t\t/* Or(%s1, %s2) -> %d1 */'
+  "emit"        => '. orl %s2, %d1\t\t\t/* Or(%s1, %s2) -> %d1, (%a1, %a2) */'
 },
 
 "Or_i" => {
@@ -227,7 +235,7 @@ $arch = "ia32";
   "comment"     => "construct Or: Or(a, const) = Or(const, a) = a OR const",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. orl %c, %d1\t\t\t/* Or(%c, %s1) -> %d1 */'
+  "emit"        => '. orl %c, %d1\t\t\t/* Or(%c, %s1) -> %d1, (%a1, const) */'
 },
 
 "Eor" => {
@@ -237,7 +245,7 @@ $arch = "ia32";
   "comment"     => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. xorl %s2, %d1\t\t\t/* Xor(%s1, %s2) -> %d1 */'
+  "emit"        => '. xorl %s2, %d1\t\t\t/* Xor(%s1, %s2) -> %d1, (%a1, %a2) */'
 },
 
 "Eor_i" => {
@@ -246,7 +254,7 @@ $arch = "ia32";
   "comment"     => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. xorl %c, %d1\t\t\t/* Xor(%c, %s1) -> %d1 */'
+  "emit"        => '. xorl %c, %d1\t\t\t/* Xor(%c, %s1) -> %d1, (%a1, const) */'
 },
 
 "Max" => {
@@ -257,7 +265,7 @@ $arch = "ia32";
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
   "emit"        =>
-'2. cmpl %s2, %s1\t\t\t/* prepare Max (%s1 should be %d1) */
+'2. cmpl %s2, %s1\t\t\t/* prepare Max (%s1 should be %d1), (%a1, %a2) */
   if (mode_is_signed(get_irn_mode(n))) {
 4.  cmovl %s2, %d1\t\t\t/* %s1 is less %s2 */
   }
@@ -275,7 +283,7 @@ $arch = "ia32";
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
   "emit"        =>
-'2. cmpl %s2, %s1\t\t\t/* prepare Min (%s1 should be %d1) */
+'2. cmpl %s2, %s1\t\t\t/* prepare Min (%s1 should be %d1), (%a1, %a2) */
   if (mode_is_signed(get_irn_mode(n))) {
 2.  cmovg %s2, %d1\t\t\t/* %s1 is greater %s2 */
   }
@@ -293,7 +301,7 @@ $arch = "ia32";
   "comment"     => "construct Sub: Sub(a, b) = a - b",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. subl %s2, %d1\t\t\t/* Sub(%s1, %s2) -> %d1 */'
+  "emit"        => '. subl %s2, %d1\t\t\t/* Sub(%s1, %s2) -> %d1, (%a1, %a2) */'
 },
 
 "Sub_i" => {
@@ -302,47 +310,49 @@ $arch = "ia32";
   "comment"     => "construct Sub: Sub(a, const) = a - const",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. subl %c, %d1\t\t\t/* Sub(%s1, %c) -> %d1 */'
+  "emit"        => '. subl %c, %d1\t\t\t/* Sub(%s1, %c) -> %d1, (%a1, const) */'
 },
 
 "DivMod" => {
+  "op_flags"    => "F|L",
+  "state"       => "exc_pinned",
   "arity"       => 4,
   "comment"     => "construct DivMod: DivMod(a,b) = (a / b, a % b)",
-  "reg_req"     => { "in" => [ "eax", "general_purpose", "edx" ], "out" => [ "eax", "edx" ] },
   "emit"        =>
 '  if (mode_is_signed(get_irn_mode(n))) {
-4.  idivl %s2\t\t\t/* signed Mod(%s1, %s2) -> %d1 */
+4.  idivl %s2\t\t\t/* signed Mod(%s1, %s2) -> %d1, (%a2, %a3, %4) */
   }
   else {
-4.  divl %s2\t\t\t/* unsigned Mod(%s1, %s2) -> %d1 */
+4.  divl %s2\t\t\t/* unsigned Mod(%s1, %s2) -> %d1, (%a2, %a3, %a4) */
   }
 ',
   "args"     => [
-                  { "type" => "ir_node *",        "name" => "mem" },
-                  { "type" => "ir_node *",        "name" => "divisor" },
                   { "type" => "ir_node *",        "name" => "dividend" },
+                  { "type" => "ir_node *",        "name" => "divisor" },
+                  { "type" => "ir_node *",        "name" => "mem" },
                   { "type" => "divmod_flavour_t", "name" => "dm_flav" },   # flavours (flavour_Div, flavour_Mod, flavour_DivMod)
                   { "type" => "ir_mode *",        "name" => "mode" },
                 ],
   "rd_constructor" =>
 "  ir_node *res;
   ir_node *in[4];
+  asmop_attr *attr;
 
   if (!op_ia32_DivMod) assert(0);
 
-  in[0] = mem;
-  in[2] = dividend;
+  in[1] = divisor;
+  in[3] = mem;
 
   if (mode_is_signed(mode)) {
     ir_node *cltd;
-    /* in signed mode , we need to sign extend the divisor */
+    /* in signed mode , we need to sign extend the dividend */
     cltd  = new_rd_ia32_Cltd(db, current_ir_graph, block, divisor, mode_T);
-    in[1] = new_rd_Proj(db, current_ir_graph, block, cltd, mode, pn_EAX);
-    in[3] = new_rd_Proj(db, current_ir_graph, block, cltd, mode, pn_EDX);
+    in[0] = new_rd_Proj(db, current_ir_graph, block, cltd, mode_Is, pn_EAX);
+    in[2] = new_rd_Proj(db, current_ir_graph, block, cltd, mode_Is, pn_EDX);
   }
   else {
-    in[1] = divisor;
-    in[3] = new_rd_ia32_Const(db, current_ir_graph, block, mode);
+    in[0] = dividend;
+    in[2] = new_rd_ia32_Const(db, current_ir_graph, block, mode_Iu);
     set_ia32_Const_type(in[2], asmop_Const);
     set_ia32_Immop_tarval(in[2], get_tarval_null(mode_Iu));
   }
@@ -352,6 +362,20 @@ $arch = "ia32";
   set_ia32_DivMod_flavour(res, dm_flav);
   set_ia32_n_res(res, 2);
 
+  attr = get_ia32_attr(res);
+
+  attr->in_req    = calloc(4, sizeof(arch_register_req_t *));
+  attr->in_req[0] = &ia32_default_req_ia32_general_purpose_eax;
+  attr->in_req[1] = &ia32_default_req_ia32_general_purpose;
+  attr->in_req[2] = &ia32_default_req_ia32_general_purpose_edx;
+  attr->in_req[3] = &ia32_default_req_none;
+
+  attr->out_req    = calloc(2, sizeof(arch_register_req_t *));
+  attr->out_req[0] = &ia32_default_req_ia32_general_purpose_eax;
+  attr->out_req[1] = &ia32_default_req_ia32_general_purpose_edx;
+
+  attr->slots = calloc(2, sizeof(arch_register_t *));
+
   return res;
 "
 },
@@ -362,7 +386,7 @@ $arch = "ia32";
   "comment"     => "construct Shl: Shl(a, b) = a << b",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. shll %s2, %d1\t\t\t/* Shl(%s1, %s2) -> %d1 */'
+  "emit"        => '. shll %s2, %d1\t\t\t/* Shl(%s1, %s2) -> %d1, (%a1, %a2) */'
 },
 
 "Shl_i" => {
@@ -371,7 +395,7 @@ $arch = "ia32";
   "comment"     => "construct Shl: Shl(a, const) = a << const",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. shll %c, %d1\t\t\t/* Shl(%s1, %c) -> %d1 */'
+  "emit"        => '. shll %c, %d1\t\t\t/* Shl(%s1, %c) -> %d1, (%a1, const) */'
 },
 
 "Shr" => {
@@ -380,7 +404,7 @@ $arch = "ia32";
   "comment"     => "construct Shr: Shr(a, b) = a >> b",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. shrl %s2, %d1\t\t\t/* Shr(%s1, %s2) -> %d1 */'
+  "emit"        => '. shrl %s2, %d1\t\t\t/* Shr(%s1, %s2) -> %d1, (%a1, %a2) */'
 },
 
 "Shr_i" => {
@@ -389,7 +413,7 @@ $arch = "ia32";
   "comment"     => "construct Shr: Shr(a, const) = a >> const",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. shrl %c, %d1\t\t\t/* Shr(%s1, %c) -> %d1 */'
+  "emit"        => '. shrl %c, %d1\t\t\t/* Shr(%s1, %c) -> %d1, (%a1, const) */'
 },
 
 "Shrs" => {
@@ -398,7 +422,7 @@ $arch = "ia32";
   "comment"     => "construct Shrs: Shrs(a, b) = a >> b",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. sarl %s2, %d1\t\t\t/* Shrs(%s1, %s2) -> %d1 */'
+  "emit"        => '. sarl %s2, %d1\t\t\t/* Shrs(%s1, %s2) -> %d1, (%a1, %a2) */'
 },
 
 "Shrs_i" => {
@@ -407,7 +431,7 @@ $arch = "ia32";
   "comment"     => "construct Shrs: Shrs(a, const) = a >> const",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. sarl %c, %d1\t\t\t/* Shrs(%s1, %c) -> %d1 */'
+  "emit"        => '. sarl %c, %d1\t\t\t/* Shrs(%s1, %c) -> %d1, (%a1, const) */'
 },
 
 "RotR" => {
@@ -416,7 +440,7 @@ $arch = "ia32";
   "comment"     => "construct RotR: RotR(a, b) = a ROTR b",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. rorl %s2, %d1\t\t\t/* RotR(%s1, %s2) -> %d1 */'
+  "emit"        => '. rorl %s2, %d1\t\t\t/* RotR(%s1, %s2) -> %d1, (%a1, %a2) */'
 },
 
 "RotL" => {
@@ -425,7 +449,7 @@ $arch = "ia32";
   "comment"     => "construct RotL: RotL(a, b) = a ROTL b",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. roll %s2, %d1\t\t\t/* RotL(%s1, %s2) -> %d1 */'
+  "emit"        => '. roll %s2, %d1\t\t\t/* RotL(%s1, %s2) -> %d1, (%a1, %a2) */'
 },
 
 "RotL_i" => {
@@ -434,7 +458,7 @@ $arch = "ia32";
   "comment"     => "construct RotL: RotL(a, const) = a ROTL const",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. roll %c, %d1\t\t\t/* RotL(%s1, %c) -> %d1 */'
+  "emit"        => '. roll %c, %d1\t\t\t/* RotL(%s1, %c) -> %d1, (%a1, const) */'
 },
 
 "Minus" => {
@@ -443,7 +467,7 @@ $arch = "ia32";
   "comment"     => "construct Minus: Minus(a) = -a",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. negl %d1\t\t\t/* Neg(%s1) -> %d1 */'
+  "emit"        => '. negl %d1\t\t\t/* Neg(%s1) -> %d1, (%a1) */'
 },
 
 "Inc" => {
@@ -452,7 +476,7 @@ $arch = "ia32";
   "comment"     => "construct Increment: Inc(a) = a++",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. incl %d1\t\t\t/* Inc(%s1) -> %d1 */'
+  "emit"        => '. incl %d1\t\t\t/* Inc(%s1) -> %d1, (%a1) */'
 },
 
 "Dec" => {
@@ -461,7 +485,7 @@ $arch = "ia32";
   "comment"     => "construct Decrement: Dec(a) = a--",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. decl %d1\t\t\t/* Dec(%s1) -> %d1 */'
+  "emit"        => '. decl %d1\t\t\t/* Dec(%s1) -> %d1, (%a1) */'
 },
 
 "Not" => {
@@ -470,7 +494,7 @@ $arch = "ia32";
   "comment"     => "construct Not: Not(a) = !a",
   "check_inout" => 1,
   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
-  "emit"        => '. notl %d1\t\t\t/* Not(%s1) -> %d1 */'
+  "emit"        => '. notl %d1\t\t\t/* Not(%s1) -> %d1, (%a1) */'
 },
 
 # other operations
@@ -481,32 +505,56 @@ $arch = "ia32";
   "comment"  => "construct Conv: Conv(a) = (conv)a"
 },
 
-"Cmp" => {
-  "op_flags" => "C",
+"CondJmp" => {
+  "op_flags" => "C|L|X|Y",
   "arity"    => 2,
-  "comment"  => "construct Cmp: Cmp(a, b) = a CMP b",
-  "reg_req"  => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "flag_register" ] },
-  "emit"     => '. cmpl %s2, %s1\t\t\t/* Cmp(%s1, %s2) -> flags */'
+  "comment"  => "construct conditional jump: CMP A, B && JMPxx LABEL",
+  "reg_req"  => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "none", "flag_register" ] },
 },
 
-"Cmp_i" => {
+"CondJmp_i" => {
+  "op_flags" => "L|X|Y",
   "arity"    => 1,
-  "comment"  => "construct Cmp: Cmp(a, const) = Cmp(const, a) = a CMP const",
-  "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "flag_register" ] },
-  "emit"     => '. cmpl %c, %s1\t\t\t/* Cmp(%s1, %c) -> flags */'
+  "comment"  => "construct conditional jump: CMP A, const && JMPxx LABEL",
+  "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "none", "flag_register" ] },
 },
 
-"Cond" => {
+"SwitchJmp" => {
+  "op_flags" => "L|X|Y",
   "arity"    => 1,
-  "comment"  => "construct Cond: evaluate Cmp node",
-  "reg_req"  => { "in" => [ "flag_register" ] }
+  "comment"  => "construct switch",
+  "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "flag_register" ] },
 },
 
 "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" =>
+'
+  if (attr_a->tp == attr_b->tp) {
+    if (attr_a->tp == asmop_SymConst) {
+      if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
+        return 1;
+      else
+        return strcmp(get_sc_name(attr_a->old_ir), get_sc_name(attr_b->old_ir));
+    }
+    else {
+      if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
+        return 1;
+
+      if (tarval_cmp(attr_a->tv, attr_b->tv) == pn_Cmp_Eq)
+        return 0;
+      else
+        return 1;
+    }
+  }
+  else
+    return 1;
+'
 },
 
 "Cltd" => {
@@ -514,70 +562,257 @@ $arch = "ia32";
   "remat"       => 1,
   "comment"     => "construct Cltd: sign extend EAX -> EDX:EAX",
   "reg_req"     => { "in" => [ "eax" ], "out" => [ "eax", "edx" ] },
-  "emit"        => '. cltd\t\t\t/* sign extend EAX -> EDX:EAX */'
+  "emit"        => '. cltd\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(mem-edge, ptr) = LD ptr",
-  "reg_req"  => { "in" => [ "none", "general_purpose" ], "out" => [ "general_purpose" ] },
-  "emit"     => '. movl (%s1), %d1\t\t\t/* Load((%s1)) -> %d1 */'
+  "comment"  => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+  "reg_req"  => { "in" => [ "general_purpose", "none" ], "out" => [ "general_purpose" ] },
+  "emit"     => '. movl (%s1), %d1\t\t\t/* Load((%s1)) -> %d1, (%a1) */'
 },
 
 "Store" => {
+  "op_flags" => "L|F",
+  "state"    => "exc_pinned",
   "arity"    => 3,
   "remat"    => 1,
-  "comment"  => "construct Store: Store(mem-edge, ptr, val) = ST ptr,val",
-  "reg_req"  => { "in" => [ "none", "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] },
-  "emit"     => '. movl %s1, (%d1)\t\t\t/* Store(%s1) -> (%d1) */'
+  "comment"  => "construct Store: Store(ptr, val, mem) = ST ptr,val",
+  "reg_req"  => { "in" => [ "general_purpose", "general_purpose", "none" ] },
+  "emit"     => '. movl %s2, (%s1)\t\t\t/* Store(%s1) -> (%s2), (%a1, %a2) */'
 },
 
 "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\t/* %d1 = %s1 + %s2 << %c + %o */'
+  "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 */'
+  "emit"     => '. leal %c(%s1), %d1\t\t\t/* %d1 = %s1 + %c, (%a1)*/'
 },
 
-"Jmp" => {
-  "arity"    => 0,
-  "comment"  => "construct Jump: Jmp(Label)",
-  "emit"     => '. jmp %l /* jump to label %l */'
+"RegParam" => {
+  "arity"    => 1,
+  "comment"  => "constructs a Register Parameter to cover parameters passed in register",
+  "reg_req"  => { "in" => [ "none" ], "out" => [ "none" ] },
+  "cmp_attr" =>
+'
+  return (attr_a->pn_code != attr_b->pn_code);
+'
 },
 
-# Call
+"StackParam" => {
+  "arity"    => 1,
+  "comment"  => "constructs a Stack Parameter to retrieve a parameter from Stack",
+  "reg_req"  => { "in" => [ "none" ], "out" => [ "general_purpose" ] },
+  "cmp_attr" =>
+'
+  return (attr_a->pn_code != attr_b->pn_code);
+'
+},
 
-"Call" => {
+"StackArg" => {
+  "arity"    => 2,
+  "comment"  => "constructs a Stack Argument to pass an argument on Stack",
+  "reg_req"  => { "in" => [ "none", "general_purpose" ], "out" => [ "none" ] },
+  "cmp_attr" =>
+'
+  return (attr_a->pn_code != attr_b->pn_code);
+'
+},
+
+#--------------------------------------------------------#
+#    __ _             _                     _            #
+#   / _| |           | |                   | |           #
+#  | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
+#  |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
+#  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
+#  |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
+#--------------------------------------------------------#
+
+# 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_s1" ] },
+  "emit"        => '. add%m %s2, %d1\t\t\t/* SSE Add(%s1, %s2) -> %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_s1" ] },
+  "emit"        =>'. muls%m %s2, %d1\t\t\t/* SSE Mul(%s1, %s2) -> %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_s1" ] },
+  "emit"        =>'. maxs%m %s2, %d1\t\t\t/* SSE Max(%s1, %s2) -> %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_s1" ] },
+  "emit"        =>'. mins%m %s2, %d1\t\t\t/* SSE Min(%s1, %s2) -> %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_s1" ] },
+  "emit"        => '. subs%m %s2, %d1\t\t\t/* SSE Sub(%s1, %s2) -> %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_s1" ] },
+  "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_s1" ] },
+  "emit"        => '. xorp%m c %d1\t\t\t/* SSE Minus(%s1) -> %d1 */'
+},
+
+# other operations
+
+"fConv" => {
   "arity"    => 1,
-  "spill"    => 0,
-  "comment"  => "construct Call: Call(...)",
-  "args"     => [ { "type" => "ir_node *", "name" => "old_call" } ],
-  "rd_constructor" =>
-"  ir_node *res;
-  ir_node *in[1];
-  asmop_attr *attr;
+  "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
+  "comment"  => "construct Conv: Conv(a) = (conv)a"
+},
 
-  if (!op_ia32_Call) assert(0);
+"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", "flag_register" ] },
+},
 
-  in[0] = get_Call_mem(old_call);
+"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" =>
+'
+  if (attr_a->tp == attr_b->tp) {
+    if (attr_a->tp == asmop_SymConst) {
+      if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
+        return 1;
+      else
+        return strcmp(get_sc_name(attr_a->old_ir), get_sc_name(attr_b->old_ir));
+    }
+    else {
+      if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
+        return 1;
+
+      if (tarval_cmp(attr_a->tv, attr_b->tv) == pn_Cmp_Eq)
+        return 0;
+      else
+        return 1;
+    }
+  }
+  else
+    return 1;
+'
+},
 
-  res = new_ir_node(db, irg, block, op_ia32_Call, mode_T, 1, in);
+# Load / Store
 
-  attr         = get_ia32_attr(res);
-  attr->old_ir = get_Call_ptr(old_call);
-  attr->n_res  = 1;
+"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 (%s1), %d1\t\t\t/* Load((%s1)) -> %d1 */'
+},
 
-  return res;
+"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, (%s1)\t\t\t/* Store(%s2) -> (%s1), (%a1, %a2) */'
+},
+
+"fStackParam" => {
+  "arity"    => 1,
+  "comment"  => "constructs a Stack Parameter to retrieve a SSE parameter from Stack",
+  "reg_req"  => { "in" => [ "none" ], "out" => [ "floating_point" ] },
+  "cmp_attr" =>
+'
+  return (attr_a->pn_code != attr_b->pn_code);
+'
+},
+
+"fStackArg" => {
+  "arity"    => 2,
+  "comment"  => "constructs a Stack Argument to pass an argument on Stack",
+  "reg_req"  => { "in" => [ "none", "floating_point" ], "out" => [ "none" ] },
+  "cmp_attr" =>
+'
+  return (attr_a->pn_code != attr_b->pn_code);
+'
+},
+
+# Call
+
+"Call" => {
+  "op_flags" => "L|F",
+  "state"    => "mem_pinned",
+  "arity"    => "variable",
+  "spill"    => 0,
+  "comment"  => "construct Call: Call(...)",
+  "args"     => [
+                  { "type" => "int",        "name" => "n" },
+                  { "type" => "ir_node **", "name" => "in" }
+                ],
+  "rd_constructor" =>
+"  if (!op_ia32_Call) assert(0);
+  return new_ir_node(db, irg, block, op_ia32_Call, mode_T, n, in);
 "
 }
 
index b6fdb10..5647fa9 100644 (file)
@@ -6,9 +6,11 @@
 #include "irgraph_t.h"
 #include "irmode_t.h"
 #include "irgmod.h"
+#include "iredges.h"
+#include "irvrfy.h"
 #include "ircons.h"
 #include "dbginfo.h"
-#include "irop_t.h"
+#include "iropt_t.h"
 #include "debug.h"
 
 #include "ia32_nodes_attr.h"
 #include "ia32_transform.h"
 #include "ia32_new_nodes.h"
 
+#include "gen_ia32_regalloc_if.h"
+
 extern ir_op *get_op_Mulh(void);
 
+static int maxnum_gpreg_args = 3;   /* maximum number of int arguments passed in registers; default 3 */
+static int maxnum_fpreg_args = 5;   /* maximum number of float arguments passed in registers; default 5 */
+
+static const arch_register_req_t **current_gpreg_param_req;
+static const arch_register_req_t **current_fpreg_param_req;
+
+/* this is the order of the assigned registers usesd for parameter passing */
+
+const arch_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
+};
+
+const arch_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
+};
+
+const arch_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
+};
+
+const arch_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
+};
+
+
+
+/****************************************************************************************************
+ *                  _        _                        __                           _   _
+ *                 | |      | |                      / _|                         | | (_)
+ *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
+ * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
+ * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
+ * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
+ *
+ ****************************************************************************************************/
+
+
+
 /* 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;
+       if (op1)
+               return is_ia32_Const(op1) ? op1 : (is_ia32_Const(op2) ? op2 : NULL);
+       else return is_ia32_Const(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_ia32_Const(op1) ? op1 : (!is_ia32_Const(op2) ? op2 : NULL);
 }
 
 
@@ -42,35 +109,35 @@ static ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
  * @return the created ia23 Add_i node
  */
 static ir_node *gen_imm_Add(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
-  ir_node *new_op;
-  tarval  *tv = get_ia32_Immop_tarval(const_op);
-  int     normal_add = 0;
-  tarval_classification_t class_tv, class_negtv;
-
-  /* const_op: tarval or SymConst? */
-  if (tv) {
-    /* optimize tarvals */
-    class_tv    = classify_tarval(tv);
-    class_negtv = classify_tarval(tarval_neg(tv));
-
-    if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */
-      DBG((mod, LEVEL_2, "optimizing Add(1) to Inc ... "));
-      new_op = new_rd_ia32_Inc(dbg, current_ir_graph, block, expr_op, mode);
-    }
-    else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */
-      DBG((mod, LEVEL_2, "optimizing Add(-1) to Dec ... "));
-      new_op = new_rd_ia32_Dec(dbg, current_ir_graph, block, expr_op, mode);
-    }
-    else
-      normal_add = 1;
-  }
-  else
-    normal_add = 1;
-
-  if (normal_add)
-    new_op = new_rd_ia32_Lea_i(dbg, current_ir_graph, block, expr_op, mode);
-
-  return new_op;
+       ir_node *new_op;
+       tarval  *tv = get_ia32_Immop_tarval(const_op);
+       int     normal_add = 0;
+       tarval_classification_t class_tv, class_negtv;
+
+       /* const_op: tarval or SymConst? */
+       if (tv) {
+               /* optimize tarvals */
+               class_tv    = classify_tarval(tv);
+               class_negtv = classify_tarval(tarval_neg(tv));
+
+               if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */
+                       DBG((mod, LEVEL_2, "optimizing Add(1) to Inc ... "));
+                       new_op = new_rd_ia32_Inc(dbg, current_ir_graph, block, expr_op, mode);
+               }
+               else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */
+                       DBG((mod, LEVEL_2, "optimizing Add(-1) to Dec ... "));
+                       new_op = new_rd_ia32_Dec(dbg, current_ir_graph, block, expr_op, mode);
+               }
+               else
+                       normal_add = 1;
+       }
+       else
+               normal_add = 1;
+
+       if (normal_add)
+               new_op = new_rd_ia32_Lea_i(dbg, current_ir_graph, block, expr_op, mode);
+
+       return new_op;
 }
 
 /**
@@ -84,50 +151,58 @@ static ir_node *gen_imm_Add(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *bloc
  * @return the created ia32 Add node
  */
 static ir_node *gen_Add(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  /* try to optimize with LEA */
-  ir_node *shli_op = is_ia32_Shl_i(op1) ? op1 : (is_ia32_Shl_i(op2) ? op2 : NULL);
-  ir_node *expr_op = shli_op == op1 ? op2 : (shli_op == op2 ? op1 : NULL);
-  int normal_add   = 0;
-  ir_node *new_op;
-
-  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, current_ir_graph, block, expr_op, get_irn_n(shli_op, 0), mode);
-          set_ia32_Immop_tarval(new_op, tv);
-          set_ia32_offs(new_op, offs);
-
-          break;
-        default:
-          normal_add = 1;
-          break;
-      }
-    }
-    else
-      normal_add = 1;
-  }
-  else
-    normal_add = 1;
-
-  if (normal_add) {
-    new_op = new_rd_ia32_Lea(dbg, current_ir_graph, block, op1, op2, mode);
-    set_ia32_Immop_tarval(new_op, get_tarval_one(mode_Iu));
-    set_ia32_offs(new_op, NULL);
-  }
-
-  return new_op;
+       ir_node *shli_op;
+       ir_node *expr_op;
+       ir_node *new_op;
+       int normal_add  = 0;
+
+       if (mode_is_float(mode)) {
+               return new_rd_ia32_fAdd(dbg, current_ir_graph, block, op1, op2, mode);
+       }
+
+       /* 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, current_ir_graph, block, expr_op, get_irn_n(shli_op, 0), mode);
+                                       set_ia32_Immop_tarval(new_op, tv);
+                                       set_ia32_offs(new_op, offs);
+
+                                       break;
+                               default:
+                                       normal_add = 1;
+                                       break;
+                       }
+               }
+               else
+                       normal_add = 1;
+       }
+       else
+               normal_add = 1;
+
+       if (normal_add) {
+               new_op = new_rd_ia32_Lea(dbg, current_ir_graph, block, op1, op2, mode);
+               set_ia32_Immop_tarval(new_op, get_tarval_one(mode_Iu));
+               set_ia32_offs(new_op, NULL);
+       }
+
+       return new_op;
 }
 
 
@@ -142,7 +217,7 @@ static ir_node *gen_Add(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, i
  * @return the created ia23 Mul_i node
  */
 static ir_node *gen_imm_Mul(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
-  return new_rd_ia32_Mul_i(dbg, current_ir_graph, block, expr_op, mode);
+       return new_rd_ia32_Mul_i(dbg, current_ir_graph, block, expr_op, mode);
 }
 
 /**
@@ -156,7 +231,10 @@ static ir_node *gen_imm_Mul(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *bloc
  * @return the created ia32 Mul node
  */
 ir_node *gen_Mul(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_Mul(dbg, current_ir_graph, block, op1, op2, mode);
+       if (mode_is_float(mode)) {
+               return new_rd_ia32_fMul(dbg, current_ir_graph, block, op1, op2, mode);
+       }
+       return new_rd_ia32_Mul(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -173,7 +251,7 @@ ir_node *gen_Mul(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node
  * @return the created ia23 Mulh_i node
  */
 static ir_node *gen_imm_Mulh(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
-  return new_rd_ia32_Mulh_i(dbg, current_ir_graph, block, expr_op, mode);
+       return new_rd_ia32_Mulh_i(dbg, current_ir_graph, block, expr_op, mode);
 }
 
 /**
@@ -189,7 +267,7 @@ static ir_node *gen_imm_Mulh(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *blo
  * @return the created ia32 Mulh node
  */
 static ir_node *gen_Mulh(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_Mulh(dbg, current_ir_graph, block, op1, op2, mode);
+       return new_rd_ia32_Mulh(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -204,7 +282,7 @@ static ir_node *gen_Mulh(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block,
  * @return the created ia23 And_i node
  */
 static ir_node *gen_imm_And(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
-  return new_rd_ia32_And_i(dbg, current_ir_graph, block, expr_op, mode);
+       return new_rd_ia32_And_i(dbg, current_ir_graph, block, expr_op, mode);
 }
 
 /**
@@ -218,7 +296,7 @@ static ir_node *gen_imm_And(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *bloc
  * @return the created ia32 And node
  */
 static ir_node *gen_And(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_And(dbg, current_ir_graph, block, op1, op2, mode);
+       return new_rd_ia32_And(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -233,7 +311,7 @@ static ir_node *gen_And(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, i
  * @return the created ia23 Or_i node
  */
 static ir_node *gen_imm_Or(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
-  return new_rd_ia32_Or_i(dbg, current_ir_graph, block, expr_op, mode);
+       return new_rd_ia32_Or_i(dbg, current_ir_graph, block, expr_op, mode);
 }
 
 /**
@@ -247,7 +325,7 @@ static ir_node *gen_imm_Or(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block
  * @return the created ia32 Or node
  */
 static ir_node *gen_Or(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_Or(dbg, current_ir_graph, block, op1, op2, mode);
+       return new_rd_ia32_Or(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -262,7 +340,7 @@ static ir_node *gen_Or(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir
  * @return the created ia23 Eor_i node
  */
 static ir_node *gen_imm_Eor(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
-  return new_rd_ia32_Eor_i(dbg, current_ir_graph, block, expr_op, mode);
+       return new_rd_ia32_Eor_i(dbg, current_ir_graph, block, expr_op, mode);
 }
 
 /**
@@ -276,7 +354,7 @@ static ir_node *gen_imm_Eor(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *bloc
  * @return the created ia32 Eor node
  */
 static ir_node *gen_Eor(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_Eor(dbg, current_ir_graph, block, op1, op2, mode);
+       return new_rd_ia32_Eor(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -291,7 +369,7 @@ static ir_node *gen_Eor(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, i
  * @return the created ia23 Max node
  */
 static ir_node *gen_Max(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_Max(dbg, current_ir_graph, block, op1, op2, mode);
+       return new_rd_ia32_Max(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -306,36 +384,7 @@ static ir_node *gen_Max(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, i
  * @return the created ia23 Min node
  */
 static ir_node *gen_Min(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_Min(dbg, current_ir_graph, block, op1, op2, mode);
-}
-
-
-
-/**
- * Creates an ia32 Cmp 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 Cmp_i node
- */
-static ir_node *gen_imm_Cmp(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
-  return new_rd_ia32_Cmp_i(dbg, current_ir_graph, block, expr_op, mode);
-}
-
-/**
- * Creates an ia32 Cmp.
- *
- * @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 Cmp node
- */
-static ir_node *gen_Cmp(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_Cmp(dbg, current_ir_graph, block, op1, op2, mode);
+       return new_rd_ia32_Min(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -350,35 +399,35 @@ static ir_node *gen_Cmp(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, i
  * @return the created ia23 Sub_i node
  */
 static ir_node *gen_imm_Sub(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
-  ir_node *new_op;
-  tarval  *tv = get_ia32_Immop_tarval(const_op);
-  int     normal_sub = 0;
-  tarval_classification_t class_tv, class_negtv;
-
-  /* const_op: tarval or SymConst? */
-  if (tv) {
-    /* optimize tarvals */
-    class_tv    = classify_tarval(tv);
-    class_negtv = classify_tarval(tarval_neg(tv));
-
-    if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */
-      DBG((mod, LEVEL_2, "optimizing Sub(1) to Dec ... "));
-      new_op = new_rd_ia32_Dec(dbg, current_ir_graph, block, expr_op, mode);
-    }
-    else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */
-      DBG((mod, LEVEL_2, "optimizing Sub(-1) to Inc ... "));
-      new_op = new_rd_ia32_Inc(dbg, current_ir_graph, block, expr_op, mode);
-    }
-    else
-      normal_sub = 1;
-  }
-  else
-    normal_sub = 1;
-
-  if (normal_sub)
-    new_op = new_rd_ia32_Sub_i(dbg, current_ir_graph, block, expr_op, mode);
-
-  return new_op;
+       ir_node *new_op;
+       tarval  *tv = get_ia32_Immop_tarval(const_op);
+       int     normal_sub = 0;
+       tarval_classification_t class_tv, class_negtv;
+
+       /* const_op: tarval or SymConst? */
+       if (tv) {
+               /* optimize tarvals */
+               class_tv    = classify_tarval(tv);
+               class_negtv = classify_tarval(tarval_neg(tv));
+
+               if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */
+                       DBG((mod, LEVEL_2, "optimizing Sub(1) to Dec ... "));
+                       new_op = new_rd_ia32_Dec(dbg, current_ir_graph, block, expr_op, mode);
+               }
+               else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */
+                       DBG((mod, LEVEL_2, "optimizing Sub(-1) to Inc ... "));
+                       new_op = new_rd_ia32_Inc(dbg, current_ir_graph, block, expr_op, mode);
+               }
+               else
+                       normal_sub = 1;
+       }
+       else
+               normal_sub = 1;
+
+       if (normal_sub)
+               new_op = new_rd_ia32_Sub_i(dbg, current_ir_graph, block, expr_op, mode);
+
+       return new_op;
 }
 
 /**
@@ -392,7 +441,10 @@ static ir_node *gen_imm_Sub(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *bloc
  * @return the created ia32 Sub node
  */
 static ir_node *gen_Sub(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_Sub(dbg, current_ir_graph, block, op1, op2, mode);
+       if (mode_is_float(mode)) {
+               return new_rd_ia32_fSub(dbg, current_ir_graph, block, op1, op2, mode);
+       }
+       return new_rd_ia32_Sub(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -408,7 +460,7 @@ static ir_node *gen_Sub(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, i
  * @return the created ia32 Mod node
  */
 static ir_node *gen_Mod(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *mem, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_DivMod(dbg, current_ir_graph, block, mem, op1, op2, flavour_Mod, mode);
+       return new_rd_ia32_DivMod(dbg, current_ir_graph, block, op1, op2, mem, flavour_Mod, mode);
 }
 
 
@@ -424,7 +476,7 @@ static ir_node *gen_Mod(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, i
  * @return the created ia32 Div node
  */
 static ir_node *gen_Div(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *mem, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_DivMod(dbg, current_ir_graph, block, mem, op1, op2, flavour_Div, mode);
+       return new_rd_ia32_DivMod(dbg, current_ir_graph, block, op1, op2, mem, flavour_Div, mode);
 }
 
 
@@ -440,7 +492,23 @@ static ir_node *gen_Div(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, i
  * @return the created ia32 DivMod node
  */
 static ir_node *gen_DivMod(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *mem, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_DivMod(dbg, current_ir_graph, block, mem, op1, op2, flavour_DivMod, mode);
+       return new_rd_ia32_DivMod(dbg, current_ir_graph, block, op1, op2, mem, flavour_DivMod, mode);
+}
+
+
+
+/**
+ * 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
+ */
+static ir_node *gen_Quot(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
+       return new_rd_ia32_fDiv(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -455,7 +523,7 @@ static ir_node *gen_DivMod(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block
  * @return the created ia23 Shl_i node
  */
 static ir_node *gen_imm_Shl(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
-  return new_rd_ia32_Shl_i(dbg, current_ir_graph, block, expr_op, mode);
+       return new_rd_ia32_Shl_i(dbg, current_ir_graph, block, expr_op, mode);
 }
 
 /**
@@ -469,7 +537,7 @@ static ir_node *gen_imm_Shl(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *bloc
  * @return the created ia32 Shl node
  */
 static ir_node *gen_Shl(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_Shl(dbg, current_ir_graph, block, op1, op2, mode);
+       return new_rd_ia32_Shl(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -484,7 +552,7 @@ static ir_node *gen_Shl(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, i
  * @return the created ia23 Shr_i node
  */
 static ir_node *gen_imm_Shr(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
-  return new_rd_ia32_Shr_i(dbg, current_ir_graph, block, expr_op, mode);
+       return new_rd_ia32_Shr_i(dbg, current_ir_graph, block, expr_op, mode);
 }
 
 /**
@@ -498,7 +566,7 @@ static ir_node *gen_imm_Shr(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *bloc
  * @return the created ia32 Shr node
  */
 static ir_node *gen_Shr(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_Shr(dbg, current_ir_graph, block, op1, op2, mode);
+       return new_rd_ia32_Shr(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -513,7 +581,7 @@ static ir_node *gen_Shr(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, i
  * @return the created ia23 Shrs_i node
  */
 static ir_node *gen_imm_Shrs(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
-  return new_rd_ia32_Shrs_i(dbg, current_ir_graph, block, expr_op, mode);
+       return new_rd_ia32_Shrs_i(dbg, current_ir_graph, block, expr_op, mode);
 }
 
 /**
@@ -527,7 +595,7 @@ static ir_node *gen_imm_Shrs(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *blo
  * @return the created ia32 Shrs node
  */
 static ir_node *gen_Shrs(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_Shrs(dbg, current_ir_graph, block, op1, op2, mode);
+       return new_rd_ia32_Shrs(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -543,7 +611,7 @@ static ir_node *gen_Shrs(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block,
  * @return the created ia32 RotL node
  */
 static ir_node *gen_RotL(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_RotL(dbg, current_ir_graph, block, op1, op2, mode);
+       return new_rd_ia32_RotL(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -561,7 +629,7 @@ static ir_node *gen_RotL(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block,
  * @return the created ia32 RotR node
  */
 static ir_node *gen_RotR(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  return new_rd_ia32_RotR(dbg, current_ir_graph, block, op1, op2, mode);
+       return new_rd_ia32_RotR(dbg, current_ir_graph, block, op1, op2, mode);
 }
 
 
@@ -578,7 +646,7 @@ static ir_node *gen_RotR(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block,
  * @return the created ia32 RotL node
  */
 static ir_node *gen_imm_Rot(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
-  return new_rd_ia32_RotL_i(dbg, current_ir_graph, block, expr_op, mode);
+       return new_rd_ia32_RotL_i(dbg, current_ir_graph, block, expr_op, mode);
 }
 
 /**
@@ -592,36 +660,36 @@ static ir_node *gen_imm_Rot(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *bloc
  * @return the created ia32 RotL or RotR node
  */
 static ir_node *gen_Rot(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
-  ir_node *rotate = NULL;
+       ir_node *rotate = NULL;
 
-  /* Firm has only Rot (which is a RotL), so we are looking for a right (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 */
+       /* Firm has only Rot (which is a RotL), so we are looking for a right (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_ia32_Add_i(op2)) {
+               ir_node *minus = get_irn_n(op2, 0); // is there an op_Minus?
 
-    if (is_ia32_Minus(minus)) {
-      tarval *tv = get_ia32_Immop_tarval(op2);
-      long bits  = get_mode_size_bits(mode);
+               if (is_ia32_Minus(minus)) {
+                       tarval *tv = get_ia32_Immop_tarval(op2);
+                       long bits  = get_mode_size_bits(mode);
 
-      if (tarval_is_long(tv) && get_tarval_long(tv) == bits) {
-        DBG((mod, LEVEL_1, "optimizing RotL into RotR ... "));
-        rotate = gen_RotR(mod, dbg, block, op1, get_irn_n(minus, 0), mode);
-      }
-    }
-  }
+                       if (tarval_is_long(tv) && get_tarval_long(tv) == bits) {
+                               DBG((mod, LEVEL_1, "optimizing RotL into RotR ... "));
+                               rotate = gen_RotR(mod, dbg, block, op1, get_irn_n(minus, 0), mode);
+                       }
+               }
+       }
 
-  if (!rotate)
-    rotate = gen_RotL(mod, dbg, block, op1, op2, mode);
+       if (!rotate)
+               rotate = gen_RotL(mod, dbg, block, op1, op2, mode);
 
-  return rotate;
+       return rotate;
 }
 
 
 
 /**
- * Transforms commutative operations (op_Add, op_Mul, op_And, op_Or, op_Eor, op_Cmp)
+ * Transforms commutative operations (op_Add, op_Mul, 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
@@ -634,94 +702,94 @@ static ir_node *gen_Rot(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, i
  * @return the created assembler node
  */
 static ir_node *gen_arith_Op(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op1, ir_node *op2, ir_mode *mode, int com) {
-  dbg_info *dbg      = get_irn_dbg_info(node);
-  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);
+       dbg_info *dbg      = get_irn_dbg_info(node);
+       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);
 
 #define GENOP(a)  case iro_##a: asm_node = gen_##a(mod, dbg, block, op1, op2, mode); break
 #define GENOPI(a) case iro_##a: asm_node = gen_imm_##a(mod, dbg, block, expr_op, imm_op, mode); 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)) {
-    DBG((mod, LEVEL_2, "found unexpected %s(Const, Const), creating binop ... ", get_irn_opname(node)));
-    imm_op = NULL;
-  }
-
-  if (op == get_op_Min() || op == get_op_Max()) {
-    DBG((mod, LEVEL_2, "MIN/MAX imm not available, creating binop ... "));
-    imm_op = NULL;
-  }
-
-  DBG((mod, LEVEL_1, "(op1: %s -- op2: %s) ... ", get_irn_opname(op1), get_irn_opname(op2)));
-
-  if (imm_op) {
-    DBG((mod, LEVEL_1, "%s with imm ... ", get_irn_opname(node)));
-
-    switch(opc) {
-      GENOPI(Add);
-      GENOPI(Mul);
-      GENOPI(And);
-      GENOPI(Or);
-      GENOPI(Eor);
-      GENOPI(Cmp);
-
-      GENOPI(Sub);
-      GENOPI(Shl);
-      GENOPI(Shr);
-      GENOPI(Shrs);
-      GENOPI(Rot);
-      default:
-        if (op == get_op_Mulh()) {
-          asm_node = gen_imm_Mulh(mod, dbg, block, expr_op, imm_op, mode);
-        }
-        else
-          assert("binop_i: THIS SHOULD NOT HAPPEN");
-    }
-
-    set_ia32_Immop_attr(asm_node, imm_op);
-  }
-  else {
-    DBG((mod, LEVEL_1, "%s as binop ... ", get_irn_opname(node)));
-
-    switch(opc) {
-      GENOP(Add);
-      GENOP(Mul);
-      GENOP(And);
-      GENOP(Or);
-      GENOP(Eor);
-      GENOP(Cmp);
-
-      GENOP(Sub);
-      GENOP(Shl);
-      GENOP(Shr);
-      GENOP(Shrs);
-      GENOP(Rot);
-      default:
-        if (op == get_op_Mulh()) {
-          asm_node = gen_Mulh(mod, dbg, block, op1, op2, mode);
-        }
-        else if (op == get_op_Max()) {
-          asm_node = gen_Max(mod, dbg, block, op1, op2, mode);
-        }
-        else if (op == get_op_Min()) {
-          asm_node = gen_Min(mod, dbg, block, op1, op2, mode);
-        }
-        else
-          assert("binop: THIS SHOULD NOT HAPPEN");
-    }
-  }
-
-  return asm_node;
+       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)) {
+               DBG((mod, LEVEL_2, "found unexpected %s(Const, Const), creating binop ... ", get_irn_opname(node)));
+               imm_op = NULL;
+       }
+
+       if (op == get_op_Min() || op == get_op_Max()) {
+               DBG((mod, LEVEL_2, "MIN/MAX imm not available, creating binop ... "));
+               imm_op = NULL;
+       }
+
+       DBG((mod, LEVEL_1, "(op1: %s -- op2: %s) ... ", get_irn_opname(op1), get_irn_opname(op2)));
+
+       if (!mode_is_float(mode) && imm_op) {
+               DBG((mod, LEVEL_1, "%s with imm ... ", get_irn_opname(node)));
+
+               switch(opc) {
+                       GENOPI(Add);
+                       GENOPI(Mul);
+                       GENOPI(And);
+                       GENOPI(Or);
+                       GENOPI(Eor);
+
+                       GENOPI(Sub);
+                       GENOPI(Shl);
+                       GENOPI(Shr);
+                       GENOPI(Shrs);
+                       GENOPI(Rot);
+                       default:
+                               if (op == get_op_Mulh()) {
+                                       asm_node = gen_imm_Mulh(mod, dbg, block, expr_op, imm_op, mode);
+                               }
+                               else
+                                       assert("binop_i: THIS SHOULD NOT HAPPEN");
+               }
+
+               set_ia32_Immop_attr(asm_node, imm_op);
+       }
+       else {
+               DBG((mod, LEVEL_1, "%s as binop ... ", get_irn_opname(node)));
+
+               switch(opc) {
+                       GENOP(Add);
+                       GENOP(Mul);
+                       GENOP(And);
+                       GENOP(Or);
+                       GENOP(Eor);
+
+                       GENOP(Quot);
+
+                       GENOP(Sub);
+                       GENOP(Shl);
+                       GENOP(Shr);
+                       GENOP(Shrs);
+                       GENOP(Rot);
+                       default:
+                               if (op == get_op_Mulh()) {
+                                       asm_node = gen_Mulh(mod, dbg, block, op1, op2, mode);
+                               }
+                               else if (op == get_op_Max()) {
+                                       asm_node = gen_Max(mod, dbg, block, op1, op2, mode);
+                               }
+                               else if (op == get_op_Min()) {
+                                       asm_node = gen_Min(mod, dbg, block, op1, op2, mode);
+                               }
+                               else
+                                       assert("binop: THIS SHOULD NOT HAPPEN");
+               }
+       }
+
+       return asm_node;
 }
 
 
@@ -737,12 +805,16 @@ static ir_node *gen_arith_Op(firm_dbg_module_t *mod, ir_node *block, ir_node *no
  * @return the created ia32 Minus node
  */
 static ir_node *gen_Minus(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) {
-  if (is_ia32_Minus(op)) {
-    DBG((mod, LEVEL_1, "optimizing --(e) to e ..."));
-    return get_irn_n(op, 0);
-  }
-  else
-    return new_rd_ia32_Minus(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
+       if (is_ia32_Minus(op) || is_ia32_fMinus(op)) {
+               DBG((mod, LEVEL_1, "optimizing --(e) to e ..."));
+               return get_irn_n(op, 0);
+       }
+       else {
+               if (mode_is_float(mode)) {
+                       return new_rd_ia32_fMinus(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
+               }
+               return new_rd_ia32_Minus(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
+       }
 }
 
 
@@ -758,7 +830,7 @@ static ir_node *gen_Minus(firm_dbg_module_t *mod, ir_node *block, ir_node *node,
  * @return the created ia32 Conv node
  */
 static ir_node *gen_Conv(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) {
-  return new_rd_ia32_Conv(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
+       return new_rd_ia32_Conv(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
 }
 
 
@@ -774,7 +846,7 @@ static ir_node *gen_Conv(firm_dbg_module_t *mod, ir_node *block, ir_node *node,
  * @return the created ia32 Not node
  */
 static ir_node *gen_Not(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) {
-  return new_rd_ia32_Not(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
+       return new_rd_ia32_Not(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
 }
 
 
@@ -790,16 +862,16 @@ static ir_node *gen_Not(firm_dbg_module_t *mod, ir_node *block, ir_node *node, i
  * @return the created ia32 Abs node
  */
 static ir_node *gen_Abs(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) {
-  ir_node  *res, *p_eax, *p_edx;
-  dbg_info *dbg = get_irn_dbg_info(node);
+       ir_node  *res, *p_eax, *p_edx;
+       dbg_info *dbg = get_irn_dbg_info(node);
 
-  res   = new_rd_ia32_Cltd(dbg, current_ir_graph, block, op, mode_T);
-  p_eax = new_rd_Proj(dbg, current_ir_graph, block, res, mode, pn_EAX);
-  p_edx = new_rd_Proj(dbg, current_ir_graph, block, res, mode, pn_EDX);
-  res   = new_rd_ia32_Eor(dbg, current_ir_graph, block, p_eax, p_edx, mode);
-  res   = new_rd_ia32_Sub(dbg, current_ir_graph, block, res, p_edx, mode);
+       res   = new_rd_ia32_Cltd(dbg, current_ir_graph, block, op, mode_T);
+       p_eax = new_rd_Proj(dbg, current_ir_graph, block, res, mode, pn_EAX);
+       p_edx = new_rd_Proj(dbg, current_ir_graph, block, res, mode, pn_EDX);
+       res   = new_rd_ia32_Eor(dbg, current_ir_graph, block, p_eax, p_edx, mode);
+       res   = new_rd_ia32_Sub(dbg, current_ir_graph, block, res, p_edx, mode);
 
-  return res;
+       return res;
 }
 
 
@@ -814,7 +886,10 @@ static ir_node *gen_Abs(firm_dbg_module_t *mod, ir_node *block, ir_node *node, i
  * @return the created ia32 Load node
  */
 static ir_node *gen_Load(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
-  return new_rd_ia32_Load(get_irn_dbg_info(node), current_ir_graph, block, get_Load_mem(node), get_Load_ptr(node), mode);
+       if (mode_is_float(mode)) {
+               return new_rd_ia32_fLoad(get_irn_dbg_info(node), current_ir_graph, block, get_Load_ptr(node), get_Load_mem(node), mode);
+       }
+       return new_rd_ia32_Load(get_irn_dbg_info(node), current_ir_graph, block, get_Load_ptr(node), get_Load_mem(node), mode);
 }
 
 
@@ -829,13 +904,38 @@ static ir_node *gen_Load(firm_dbg_module_t *mod, ir_node *block, ir_node *node,
  * @return the created ia32 Store node
  */
 ir_node *gen_Store(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
-  return new_rd_ia32_Store(get_irn_dbg_info(node), current_ir_graph, block, get_Store_mem(node), get_Store_ptr(node), get_Store_value(node), mode);
+       if (mode_is_float(mode)) {
+               return new_rd_ia32_fStore(get_irn_dbg_info(node), current_ir_graph, block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), mode);
+       }
+       return new_rd_ia32_Store(get_irn_dbg_info(node), current_ir_graph, block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), mode);
 }
 
 
 
 /**
- * Transforms a Call.
+ * Check all parameters and determine the maximum number of parameters
+ * to pass in gp regs resp. in fp regs.
+ */
+static void get_n_regparam_class(int n, ir_node **param, int *n_int, int *n_float) {
+       int i;
+
+       for (i = 0; i < n; i++) {
+               if (mode_is_int(get_irn_mode(param[i])))
+                       *n_int = *n_int + 1;
+               else if (mode_is_float(get_irn_mode(param[i])))
+                       *n_float = *n_float + 1;
+
+               /* test for maximum */
+               if (*n_int == maxnum_gpreg_args)
+                       break;
+
+               if (*n_float == maxnum_fpreg_args)
+                       break;
+       }
+}
+
+/**
+ * Transforms a Call and its arguments corresponding to the calling convention.
  *
  * @param mod     the debug module
  * @param block   the block the new node should belong to
@@ -843,12 +943,167 @@ ir_node *gen_Store(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mod
  * @param dummy   mode doesn't matter
  * @return the created ia32 Call node
  */
-static ir_node *gen_Call(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *dummy) {
-  return new_rd_ia32_Call(get_irn_dbg_info(node), current_ir_graph, block, node);
+static ir_node *gen_Call(firm_dbg_module_t *mod, ir_node *block, ir_node *call, ir_mode *dummy) {
+       const arch_register_req_t **in_req;
+       ir_node    **in;
+       ir_node     *new_call, *sync;
+       ir_mode     *mode;
+       int          i, j, n_new_call_in;
+       asmop_attr  *attr;
+       ir_node    **stack_param  = NULL;
+       ir_node    **param        = get_Call_param_arr(call);
+       ir_node     *call_Mem     = get_Call_mem(call);
+       unsigned     cc           = get_method_calling_convention(get_Call_type(call));
+       int          n            = get_Call_n_params(call);
+       int          n_gpregparam = 0;
+       int          n_fpregparam = 0;
+       int          cur_gp_idx   = 0;
+       int          cur_fp_idx   = 0;
+       int          stack_idx    = 0;
+       int          done         = 0;
+
+       if (cc & cc_reg_param)
+               get_n_regparam_class(n, param, &n_gpregparam, &n_fpregparam);
+
+       /* do we need to pass arguments on stack? */
+       if (n - n_gpregparam - n_fpregparam > 0)
+               stack_param = calloc(n - n_gpregparam - n_fpregparam, sizeof(ir_node *));
+
+       /* we need at least one in, either for the stack params or the call_Mem */
+       n_new_call_in = 1 + n_gpregparam + n_fpregparam;
+
+       current_gpreg_param_req = gpreg_param_req_std;
+       current_fpreg_param_req = fpreg_param_req_std;
+
+       if (cc & cc_this_call) {
+               current_gpreg_param_req = gpreg_param_req_this;
+               current_fpreg_param_req = fpreg_param_req_this;
+       }
+
+       /* the call has one IN for all stack parameter and one IN for each reg param */
+       in     = calloc(n_new_call_in, sizeof(ir_node *));
+       in_req = calloc(n_new_call_in, sizeof(arch_register_req_t *));
+
+       /* loop over all parameters and determine whether its a int or float register parameter */
+       for (i = 0; i < n && !done && (cc & cc_reg_param); i++) {
+               mode = get_irn_mode(param[i]);
+
+               if (mode_is_int(mode) && cur_gp_idx < maxnum_gpreg_args) {
+                       /* param can be passed in general purpose register and we have some registers left */
+                       in[cur_gp_idx + cur_fp_idx] = param[i];
+                       in_req[cur_gp_idx] = current_gpreg_param_req[cur_gp_idx];
+                       cur_gp_idx++;
+               }
+               else if (mode_is_float(mode) && cur_fp_idx < maxnum_fpreg_args) {
+                       /* param can be passed in floating point register and we have some registers left */
+                       assert(current_gpreg_param_req[cur_fp_idx] && "'this' pointer cannot be passed as float");
+                       in[cur_gp_idx + cur_fp_idx] = param[i];
+                       in_req[cur_fp_idx] = current_gpreg_param_req[cur_fp_idx];
+                       cur_fp_idx++;
+               }
+
+               /* maximum number of register parameters in one class reached? */
+               if (cur_gp_idx >= maxnum_gpreg_args || cur_fp_idx >= maxnum_fpreg_args) {
+                       done      = 1;
+               }
+       }
+       stack_idx = i;
+
+       /* create remaining stack parameters */
+       if (cc & cc_last_on_top) {
+               for (i = stack_idx; i < n; i++) {
+                       /* pass it on stack */
+                       if (mode_is_float(get_irn_mode(param[i]))) {
+                               stack_param[i] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), current_ir_graph,
+                                                                                                               block, call_Mem, param[i], mode_M);
+                       }
+                       else {
+                               stack_param[i] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), current_ir_graph,
+                                                                                                               block, call_Mem, param[i], mode_M);
+                       }
+               }
+       }
+       else {
+               for (i = n - 1, j = stack_idx; i >= stack_idx; i--, j++) {
+                       /* pass it on stack */
+                       if (mode_is_float(get_irn_mode(param[i]))) {
+                               stack_param[i] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), current_ir_graph,
+                                                                                                               block, call_Mem, param[i], mode_M);
+                       }
+                       else {
+                               stack_param[i] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), current_ir_graph,
+                                                                                                               block, call_Mem, param[i], mode_M);
+                       }
+               }
+       }
+
+       if (stack_param) {
+               sync = new_r_Sync(current_ir_graph, block, n - n_gpregparam - n_fpregparam, stack_param);
+               in[n_new_call_in - 1] = sync;
+       }
+       else {
+               in[n_new_call_in - 1] = call_Mem;
+       }
+
+       /* create the new node */
+       new_call = new_rd_ia32_Call(get_irn_dbg_info(call), current_ir_graph, block, n_new_call_in, in);
+       set_ia32_Immop_attr(new_call, get_Call_ptr(call));
+       set_ia32_n_res(new_call, 1);
+
+       /* set register requirements for in and out */
+       attr             = get_ia32_attr(new_call);
+       attr->in_req     = in_req;
+       attr->out_req    = calloc(1, sizeof(arch_register_req_t *));
+       attr->out_req[0] = &ia32_default_req_ia32_general_purpose_eax;
+       attr->slots      = calloc(1, sizeof(arch_register_t *));
+
+       /* stack parameter has no OUT register */
+       attr->in_req[n_new_call_in - 1] = &ia32_default_req_none;
+
+       return new_call;
 }
 
 
 
+/**
+ * creates a unique ident by adding a number to a tag
+ *
+ * @param tag   the tag string, must contain a %d if a number
+ *              should be added
+ */
+static ident *unique_id(const char *tag)
+{
+  static unsigned id = 0;
+  char str[256];
+
+  snprintf(str, sizeof(str), tag, ++id);
+  return new_id_from_str(str);
+}
+
+/**
+ * Transforms a SymConst.
+ *
+ * @param mod     the debug module
+ * @param block   the block the new node should belong to
+ * @param node    the ir SymConst node
+ * @param mode    mode of the SymConst
+ * @return the created ia32 Const node
+ */
+static ir_node *gen_SymConst(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
+       ir_node *cnst;
+
+       if (mode_is_float(mode)) {
+               cnst = new_rd_ia32_fConst(get_irn_dbg_info(node), current_ir_graph, block, mode);
+
+       }
+       else {
+               cnst = new_rd_ia32_Const(get_irn_dbg_info(node), current_ir_graph, block, mode);
+       }
+
+       set_ia32_Const_attr(cnst, node);
+       return cnst;
+}
+
 /**
  * Transforms a Const.
  *
@@ -859,28 +1114,262 @@ static ir_node *gen_Call(firm_dbg_module_t *mod, ir_node *block, ir_node *node,
  * @return the created ia32 Const node
  */
 static ir_node *gen_Const(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
-  ir_node *cnst = new_rd_ia32_Const(get_irn_dbg_info(node), current_ir_graph, block, mode);
-  set_ia32_Const_attr(cnst, node);
-  return cnst;
+       ir_node *cnst;
+       entity  *ent;
+       type    *tp;
+       symconst_symbol sym;
+
+       if (mode_is_float(mode)) {
+               tp  = get_Const_type(node);
+               if (tp == firm_unknown_type) {
+                       tp = new_type_primitive(unique_id("tp_ia32_float_%u"), mode);
+               }
+
+               ent = new_entity(get_glob_type(), unique_id("ia32FloatCnst_%u"), tp);
+
+               set_entity_ld_ident(ent, get_entity_ident(ent));
+               set_entity_visibility(ent, visibility_local);
+               set_entity_variability(ent, variability_constant);
+               set_entity_allocation(ent, allocation_static);
+
+               set_atomic_ent_value(ent, node);
+
+               sym.entity_p = ent;
+
+               cnst = new_rd_SymConst(get_irn_dbg_info(node), current_ir_graph, block, sym, symconst_addr_ent);
+               cnst = gen_SymConst(mod, block, cnst, mode);
+       }
+       else {
+               cnst = new_rd_ia32_Const(get_irn_dbg_info(node), current_ir_graph, block, mode);
+               set_ia32_Const_attr(cnst, node);
+       }
+
+       return cnst;
 }
 
+
+
 /**
- * Transforms a SymConst.
+ * 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 SymConst node
- * @param mode    mode of the SymConst
- * @return the created ia32 Const node
+ * @param node    the ir Cond node
+ * @param mode    mode of the Cond
+ * @return The transformed node.
  */
-static ir_node *gen_SymConst(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
-  ir_node *cnst = new_rd_ia32_Const(get_irn_dbg_info(node), current_ir_graph, block, mode);
-  set_ia32_Const_attr(cnst, node);
-  return cnst;
+static ir_node *gen_Cond(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
+       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;
+
+       if (is_Proj(sel) && sel_mode == mode_b) {
+               pred  = get_Proj_pred(sel);
+
+               /* get both compare operators */
+               cmp_a = get_Cmp_left(pred);
+               cmp_b = get_Cmp_right(pred);
+
+               /* check if we can use a CondJmp with immediate */
+               cnst = get_immediate_op(cmp_a, cmp_b);
+               expr = get_expr_op(cmp_a, cmp_b);
+
+               if (cnst && expr) {
+                       res = new_rd_ia32_CondJmp_i(get_irn_dbg_info(node), current_ir_graph, block, expr, mode_T);
+                       set_ia32_Immop_attr(res, cnst);
+               }
+               else {
+                       res = new_rd_ia32_CondJmp(get_irn_dbg_info(node), current_ir_graph, block, cmp_a, cmp_b, mode_T);
+               }
+
+               set_ia32_pncode(res, get_Proj_proj(sel));
+       }
+       else {
+               res = new_rd_ia32_SwitchJmp(get_irn_dbg_info(node), current_ir_graph, block, sel, mode_T);
+               set_ia32_pncode(res, get_Cond_defaultProj(node));
+       }
+
+       return res;
+}
+
+
+
+/**
+ * Transform the argument projs from a start node corresponding to the
+ * calling convention.
+ * It transforms "Proj Arg x -> ProjT -> Start <- ProjM" into
+ * "RegParam x   -> ProjT -> Start" OR
+ * "StackParam x -> ProjM -> Start"
+ * whether parameter is passed in register or on stack.
+ *
+ * @param mod     the debug module
+ * @param block   the block the nodes should belong to
+ * @param proj    the ProjT node which points to Start
+ * @param start   the Start node
+ * @return Should be always NULL
+ */
+static ir_node *gen_Proj_Start(firm_dbg_module_t *mod, ir_node *block, ir_node *proj, ir_node *start) {
+       const ir_edge_t *edge;
+       ir_node         *succ, *irn;
+       ir_node        **projargs;
+       ir_mode         *mode;
+       int              n, i, j;
+       unsigned         cc;
+       ir_node         *proj_M     = get_irg_initial_mem(current_ir_graph);
+       entity          *irg_ent    = get_irg_entity(current_ir_graph);
+       type            *tp         = get_entity_type(irg_ent);
+       int              cur_gp_idx = 0;
+       int              cur_fp_idx = 0;
+       int              stack_idx  = 0;
+       int              done       = 0;
+
+       assert(is_Method_type(tp) && "irg type is not a method");
+
+       switch(get_Proj_proj(proj)) {
+               case pn_Start_T_args:
+                       /* We cannot use get_method_n_params here as the function might
+                          be variadic or one argument is not used. */
+                       n  = get_irn_n_edges(proj);
+
+                       /* we are done here when there are no parameters */
+                       if (n < 1)
+                               break;
+
+                       /* temporary remember all proj arg x */
+                       projargs = calloc(n, sizeof(ir_node *));
+
+                       foreach_out_edge((const ir_node *)proj, edge) {
+                               succ = get_edge_src_irn(edge);
+                               assert(is_Proj(succ) && "non-Proj from a Proj_T (pn_Start_T_args).");
+                               projargs[get_Proj_proj(succ)] = succ;
+                       }
+
+                       cc = get_method_calling_convention(tp);
+
+                       /* get the correct order in case of 'this' call */
+                       current_gpreg_param_req = gpreg_param_req_std;
+                       current_fpreg_param_req = fpreg_param_req_std;
+                       if (cc & cc_this_call) {
+                               current_gpreg_param_req = gpreg_param_req_this;
+                               current_fpreg_param_req = fpreg_param_req_this;
+                       }
+
+                       /* loop over all parameters and check whether its a int or float */
+                       for (i = 0; i < n && !done && (cc & cc_reg_param); i++) {
+                               mode = get_irn_mode(projargs[i]);
+
+                               if (mode_is_int(mode) && cur_gp_idx < maxnum_gpreg_args) {
+                                       /* parameter got passed in general purpose register */
+                                       irn = new_rd_ia32_RegParam(get_irn_dbg_info(proj), current_ir_graph, block, proj, mode);
+                                       set_ia32_pncode(irn, i);
+                                       set_ia32_regreq_out(irn, current_gpreg_param_req[cur_gp_idx], 0);
+                                       cur_gp_idx++;
+                               }
+                               else if (mode_is_float(mode) && cur_fp_idx < maxnum_fpreg_args) {
+                                       /* parameter got passed in floating point register*/
+                                       irn = new_rd_ia32_RegParam(get_irn_dbg_info(proj), current_ir_graph, block, proj, mode);
+                                       set_ia32_pncode(irn, i);
+                                       set_ia32_regreq_out(irn, current_fpreg_param_req[cur_fp_idx], 0);
+                                       cur_fp_idx++;
+                               }
+
+                               /* kill the old "Proj Arg" and replace with the new Arg */
+                               exchange(projargs[i], irn);
+
+                               if (cur_gp_idx >= maxnum_gpreg_args || cur_fp_idx >= maxnum_fpreg_args) {
+                                       stack_idx = i;
+                                       done      = 1;
+                               }
+                       }
+
+                       /* create all remaining stack parameters */
+                       if (cc & cc_last_on_top) {
+                               for (i = stack_idx; i < n; i++) {
+                                       mode = get_irn_mode(projargs[i]);
+
+                                       if (mode_is_float(mode))
+                                               irn = new_rd_ia32_fStackParam(get_irn_dbg_info(projargs[i]), current_ir_graph, block, proj_M, mode);
+                                       else
+                                               irn = new_rd_ia32_StackParam(get_irn_dbg_info(projargs[i]), current_ir_graph, block, proj_M, mode);
+
+                                       set_ia32_pncode(irn, i);
+
+                                       /* kill the old "Proj Arg" and replace with the new stack param */
+                                       exchange(projargs[i], irn);
+                               }
+                       }
+                       else {
+                               for (i = n - 1, j = stack_idx; i >= stack_idx; i--, j++) {
+                                       mode = get_irn_mode(projargs[i]);
+
+                                       if (mode_is_float(mode))
+                                               irn = new_rd_ia32_fStackParam(get_irn_dbg_info(projargs[i]), current_ir_graph, block, proj_M, mode);
+                                       else
+                                               irn = new_rd_ia32_StackParam(get_irn_dbg_info(projargs[i]), current_ir_graph, block, proj_M, mode);
+
+                                       set_ia32_pncode(irn, j);
+
+                                       /* kill the old "Proj Arg" and replace with the new stack param */
+                                       exchange(projargs[i], irn);
+                               }
+                       }
+
+                       free(projargs);
+
+                       break;
+               case pn_Start_X_initial_exec:
+               case pn_Start_M:
+               case pn_Start_P_frame_base:
+               case pn_Start_P_globals:
+               case pn_Start_P_value_arg_base:
+                       break;
+               default:
+                       assert(0 && "unsupported Proj(Start)");
+       }
+
+       return NULL;
+}
+
+/**
+ * Transform some Proj's (Proj_Proj, Proj_Start, Proj_Cmp, Proj_Cond, Proj_Call).
+ * All others are ignored.
+ *
+ * @param mod     the debug module
+ * @param block   the block the new node should belong to
+ * @param node    the ir Proj node
+ * @param mode    mode of the Proj
+ * @return The transformed node.
+ */
+static ir_node *gen_Proj(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
+       ir_node *new_node  = NULL;
+       ir_node *pred      = get_Proj_pred(node);
+
+       if (mode == mode_M)
+               return NULL;
+
+       if (get_irn_op(pred) == op_Start) {
+               new_node = gen_Proj_Start(mod, block, node, pred);
+       }
+
+       return new_node;
 }
 
 
 
+/*********************************************************
+ *                  _             _      _
+ *                 (_)           | |    (_)
+ *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
+ * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
+ * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
+ * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
+ *
+ *********************************************************/
+
+
+
 /**
  * Transforms the given firm node (and maybe some other related nodes)
  * into one or more assembler nodes.
@@ -889,17 +1378,17 @@ static ir_node *gen_SymConst(firm_dbg_module_t *mod, ir_node *block, ir_node *no
  * @param env     the debug module
  */
 void ia32_transform_node(ir_node *node, void *env) {
-  firm_dbg_module_t *mod = (firm_dbg_module_t *)env;
-  opcode  code           = get_irn_opcode(node);
-  ir_node *asm_node      = NULL;
-  ir_node *block;
-  ir_mode *mode;
+       firm_dbg_module_t *mod = (firm_dbg_module_t *)env;
+       opcode  code           = get_irn_opcode(node);
+       ir_node *asm_node      = NULL;
+       ir_node *block;
+       ir_mode *mode;
 
-  if (is_Block(node))
-    return;
+       if (is_Block(node))
+               return;
 
-  block = get_nodes_block(node);
-  mode  = get_irn_mode(node);
+       block = get_nodes_block(node);
+       mode  = get_irn_mode(node);
 
 #define BINOP_COM(a)   case iro_##a: asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 1); break
 #define BINOP_NCOM(a)  case iro_##a: asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 0); break
@@ -909,84 +1398,84 @@ void ia32_transform_node(ir_node *node, void *env) {
 #define IGN(a)         case iro_##a: break
 #define BAD(a)         case iro_##a: goto bad
 
-  DBG((mod, LEVEL_1, "transforming node %s (%ld) ... ", get_irn_opname(node), get_irn_node_nr(node)));
-
-  switch (code) {
-    BINOP_COM(Add);
-    BINOP_COM(Mul);
-    BINOP_COM(And);
-    BINOP_COM(Or);
-    BINOP_COM(Eor);
-    BINOP_COM(Cmp);
-
-    BINOP_NCOM(Sub);
-    TRIOP(Mod);
-    TRIOP(Div);
-    TRIOP(DivMod);
-    BINOP_NCOM(Shl);
-    BINOP_NCOM(Shr);
-    BINOP_NCOM(Shrs);
-
-    UNOP(Minus);
-    UNOP(Conv);
-    UNOP(Abs);
-    UNOP(Not);
-
-    GEN(Load);
-    GEN(Store);
-    GEN(Call);
-    GEN(Const);
-    GEN(SymConst);
-
-    IGN(Block);
-    IGN(Start);
-    IGN(End);
-    IGN(NoMem);
-    IGN(Phi);
-    IGN(Cond);
-    IGN(Jmp);
-    IGN(IJmp);
-    IGN(Proj);
-    IGN(Break);
-
-    BAD(Raise);
-    BAD(Sel);
-    BAD(InstOf);
-    BAD(Quot);
-    BAD(Cast);
-    BAD(Alloc);
-    BAD(Free);
-    BAD(Sync);
-    BAD(Tuple);
-    BAD(Id);
-    BAD(Bad);
-    BAD(Confirm);
-    BAD(Unknown);
-    BAD(Filter);
-    BAD(CallBegin);
-    BAD(EndReg);
-    BAD(EndExcept);
-    BAD(Mux);
-    BAD(CopyB);
-
-    default:
-      if (get_irn_op(node) == get_op_Mulh() ||
-          get_irn_op(node) == get_op_Max()  ||
-          get_irn_op(node) == get_op_Min())
-      {
-        asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 1);
-      }
-      break;
+       DBG((mod, LEVEL_1, "transforming node %s (%ld) ... ", get_irn_opname(node), get_irn_node_nr(node)));
+
+       switch (code) {
+               BINOP_COM(Add);
+               BINOP_COM(Mul);
+               BINOP_COM(And);
+               BINOP_COM(Or);
+               BINOP_COM(Eor);
+
+               BINOP_NCOM(Sub);
+               TRIOP(Mod);
+               TRIOP(Div);
+               TRIOP(DivMod);
+               BINOP_NCOM(Shl);
+               BINOP_NCOM(Shr);
+               BINOP_NCOM(Shrs);
+               BINOP_NCOM(Quot);
+
+               UNOP(Minus);
+               UNOP(Conv);
+               UNOP(Abs);
+               UNOP(Not);
+
+               GEN(Load);
+               GEN(Store);
+               GEN(Call);
+               GEN(Const);
+               GEN(SymConst);
+               GEN(Cond);
+
+               GEN(Proj);
+
+               IGN(Block);
+               IGN(Start);
+               IGN(End);
+               IGN(NoMem);
+               IGN(Phi);
+               IGN(IJmp);
+               IGN(Break);
+               IGN(Cmp);
+
+               BAD(Raise);
+               BAD(Sel);
+               BAD(InstOf);
+               BAD(Cast);
+               BAD(Alloc);
+               BAD(Free);
+               BAD(Sync);
+               BAD(Tuple);
+               BAD(Id);
+               BAD(Bad);
+               BAD(Confirm);
+               BAD(Unknown);
+               BAD(Filter);
+               BAD(CallBegin);
+               BAD(EndReg);
+               BAD(EndExcept);
+               BAD(Mux);
+               BAD(CopyB);
+
+               default:
+                       if (get_irn_op(node) == get_op_Mulh() ||
+                                       get_irn_op(node) == get_op_Max()  ||
+                                       get_irn_op(node) == get_op_Min())
+                       {
+                               asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 1);
+                       }
+                       break;
 bad:
-    fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
-    assert(0);
-  }
-
-  if (asm_node) {
-    exchange(node, asm_node);
-    DBG((mod, LEVEL_1, "created node %u\n", get_irn_node_nr(asm_node)));
-  }
-  else {
-    DBG((mod, LEVEL_1, "ignored\n"));
-  }
+               fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
+               assert(0);
+       }
+
+       if (asm_node) {
+               exchange(node, asm_node);
+               DBG((mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
+       }
+       else {
+               DBG((mod, LEVEL_1, "ignored\n"));
+       }
 }