- Introduce nodemap
authorMatthias Braun <matze@braunis.de>
Mon, 25 Jun 2007 19:25:43 +0000 (19:25 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 25 Jun 2007 19:25:43 +0000 (19:25 +0000)
- All float operations depend on fpu mode now
- Fix bestate switcher
- Add and fix fehler22 (unknown phi operands in x87 simulator)

[r14749]

24 files changed:
include/libfirm/adt/cpset.h
include/libfirm/adt/hashset.h
include/libfirm/adt/pset_new.h
ir/adt/cpset.c
ir/adt/hashset.c
ir/adt/pset_new.c
ir/be/bestate.c
ir/be/ia32/bearch_ia32.c
ir/be/ia32/ia32_finish.c
ir/be/ia32/ia32_fpu.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_optimize.c
ir/be/ia32/ia32_spec.pl
ir/be/ia32/ia32_transform.c
ir/be/ia32/ia32_x87.c
ir/be/test/bad_ones [deleted file]
ir/be/test/fehler22.c
ir/be/test/good_ones [deleted file]
ir/ir/irnodeset.c
ir/ir/irnodeset.h
ir/opt/reassoc.c
ir/tv/tv.c

index 60e06d8..77934a8 100644 (file)
@@ -39,11 +39,6 @@ typedef int (*cpset_cmp_function) (const void *p1, const void *p2);
 
 /**
  * The type of a cpset hash function.
- *
- * @param p1   pointer to an element
- * @param p2   pointer to another element
- *
- * @return  1 if the elements are identically, zero else
  */
 typedef unsigned (*cpset_hash_function) (const void *obj);
 
@@ -59,6 +54,9 @@ typedef unsigned (*cpset_hash_function) (const void *obj);
 #undef HashSetIterator
 #undef HashSet
 
+typedef struct cpset_t          cpset_t;
+typedef struct cpset_iterator_t cpset_iterator_t;
+
 /**
  * Initializes a cpset
  *
index 9495ef0..54e49ca 100644 (file)
@@ -40,7 +40,7 @@ typedef struct HashSetEntry {
 } HashSetEntry;
 #endif
 
-typedef struct HashSet {
+struct HashSet {
        HashSetEntry *entries;
        size_t num_buckets;
        size_t enlarge_threshold;
@@ -54,16 +54,16 @@ typedef struct HashSet {
 #ifdef ADDITIONAL_DATA
        ADDITIONAL_DATA
 #endif
-} HashSet;
+};
 
-typedef struct HashSetIterator {
+struct HashSetIterator {
        HashSetEntry *current_bucket;
        HashSetEntry *end;
 #ifndef NDEBUG
-       const HashSet *set;
+       const struct HashSet *set;
        unsigned entries_version;
 #endif
-} HashSetIterator;
+};
 
 #ifdef DO_REHASH
 #undef HashSetEntry
index 357f17c..08a47ab 100644 (file)
@@ -42,6 +42,9 @@
 #undef HashSetIterator
 #undef ValueType
 
+typedef struct pset_new_t           pset_new_t;
+typedef struct pset_new_iterator_t  pset_new_iterator_t;
+
 /**
  * Initializes a pset_new
  *
index f5a0a26..d13447c 100644 (file)
@@ -36,8 +36,9 @@
 #define ValueType                 void*
 #define NullValue                 NULL
 #define DeletedValue              ((void*)-1)
-#define Hash(this,value)          this->hash_function(value)
+#define Hash(this,key)            this->hash_function(key)
 #define KeysEqual(this,key1,key2) this->cmp_function(key1, key2)
+#define SCALAR_RETURN
 #define SetRangeEmpty(ptr,size)   memset(ptr, 0, (size) * sizeof(cpset_hashset_entry_t))
 
 #define hashset_init            _cpset_init
index b3af299..08869b7 100644 (file)
 
 #ifndef Hash
 #define ID_HASH
-#define Hash(self,value)      ((unsigned)(value))
+#define Hash(self,key)        ((unsigned)(key))
 #endif /* Hash */
 
 #ifdef DO_REHASH
 #define HashSetEntry                   ValueType
 #define EntrySetHash(entry,new_hash)
-#define EntryGetHash(self,entry)       Hash(self,entry)
+#define EntryGetHash(self,entry)       Hash(self, GetKey(entry))
 #define EntryGetValue(entry)           (entry)
 #else /* ! DO_REHASH */
 #define EntryGetHash(self,entry)       (entry).hash
 #endif /* Alloc */
 
 #ifdef ID_HASH
-#define InsertReturnValue               int
-#define GetInsertReturnValue(entry,new) (new)
+#define InsertReturnValue                 int
+#define GetInsertReturnValue(entry,found) (found)
+#define NullReturnValue                   0
 #else /* ! ID_HASH */
-#define InsertReturnValue               ValueType
-#define GetInsertReturnValue(entry,new) EntryGetValue(entry)
+#ifdef SCALAR_RETURN
+#define InsertReturnValue                 ValueType
+#define GetInsertReturnValue(entry,found) EntryGetValue(entry)
+#define NullReturnValue                   NullValue
+#else
+#define InsertReturnValue                 ValueType*
+#define GetInsertReturnValue(entry,found) & EntryGetValue(entry)
+#define NullReturnValue                   & NullValue
+#endif
 #endif /* ID_HASH */
 
 #ifndef KeyType
@@ -211,12 +219,12 @@ size_t hashset_size(const HashSet *self)
 static INLINE
 InsertReturnValue insert_nogrow(HashSet *self, KeyType key)
 {
-       size_t num_probes = 0;
-       size_t num_buckets = self->num_buckets;
-       size_t hashmask = num_buckets - 1;
-       unsigned hash = Hash(self, key);
-       size_t bucknum = hash & hashmask;
-       size_t insert_pos = ILLEGAL_POS;
+       size_t   num_probes  = 0;
+       size_t   num_buckets = self->num_buckets;
+       size_t   hashmask    = num_buckets - 1;
+       unsigned hash        = Hash(self, key);
+       size_t   bucknum     = hash & hashmask;
+       size_t   insert_pos  = ILLEGAL_POS;
 
        assert((num_buckets & (num_buckets - 1)) == 0);
 
@@ -237,7 +245,7 @@ InsertReturnValue insert_nogrow(HashSet *self, KeyType key)
                        InitData(self, EntryGetValue(*nentry), key);
                        EntrySetHash(*nentry, hash);
                        self->num_elements++;
-                       return GetInsertReturnValue(*nentry, 1);
+                       return GetInsertReturnValue(*nentry, 0);
                }
                if(EntryIsDeleted(*entry)) {
                        if(insert_pos == ILLEGAL_POS)
@@ -245,7 +253,7 @@ InsertReturnValue insert_nogrow(HashSet *self, KeyType key)
                } else if(EntryGetHash(self, *entry) == hash) {
                        if(KeysEqual(self, GetKey(EntryGetValue(*entry)), key)) {
                                // Value already in the set, return it
-                               return GetInsertReturnValue(*entry, 0);
+                               return GetInsertReturnValue(*entry, 1);
                        }
                }
 
@@ -263,13 +271,13 @@ InsertReturnValue insert_nogrow(HashSet *self, KeyType key)
 static
 void insert_new(HashSet *self, unsigned hash, ValueType value)
 {
-       size_t num_probes = 0;
+       size_t num_probes  = 0;
        size_t num_buckets = self->num_buckets;
-       size_t hashmask = num_buckets - 1;
-       size_t bucknum = hash & hashmask;
-       size_t insert_pos = ILLEGAL_POS;
+       size_t hashmask    = num_buckets - 1;
+       size_t bucknum     = hash & hashmask;
+       size_t insert_pos  = ILLEGAL_POS;
 
-       assert(value != NullValue);
+       //assert(value != NullValue);
 
        while(1) {
                HashSetEntry *entry = & self->entries[bucknum];
@@ -306,8 +314,8 @@ static INLINE
 void reset_thresholds(HashSet *self)
 {
        self->enlarge_threshold = (size_t) HT_OCCUPANCY_FLT(self->num_buckets);
-       self->shrink_threshold = (size_t) HT_EMPTY_FLT(self->num_buckets);
-       self->consider_shrink = 0;
+       self->shrink_threshold  = (size_t) HT_EMPTY_FLT(self->num_buckets);
+       self->consider_shrink   = 0;
 }
 
 /**
@@ -327,10 +335,10 @@ void resize(HashSet *self, size_t new_size)
        SetRangeEmpty(new_entries, new_size);
 
        /* use the new array */
-       self->entries = new_entries;
-       self->num_buckets = new_size;
+       self->entries      = new_entries;
+       self->num_buckets  = new_size;
        self->num_elements = 0;
-       self->num_deleted = 0;
+       self->num_deleted  = 0;
 #ifndef NDEBUG
        self->entries_version++;
 #endif
@@ -423,26 +431,26 @@ InsertReturnValue hashset_insert(HashSet *self, KeyType key)
  * @param key       the key to search for
  * @returns         the found value or NullValue if nothing was found
  */
-ValueType hashset_find(const HashSet *self, ConstKeyType key)
+InsertReturnValue hashset_find(const HashSet *self, ConstKeyType key)
 {
-       size_t num_probes = 0;
-       size_t num_buckets = self->num_buckets;
-       size_t hashmask = num_buckets - 1;
-       unsigned hash = Hash(self, key);
-       size_t bucknum = hash & hashmask;
+       size_t   num_probes  = 0;
+       size_t   num_buckets = self->num_buckets;
+       size_t   hashmask    = num_buckets - 1;
+       unsigned hash        = Hash(self, key);
+       size_t   bucknum     = hash & hashmask;
 
        while(1) {
                HashSetEntry *entry = & self->entries[bucknum];
 
                if(EntryIsEmpty(*entry)) {
-                       return NullValue;
+                       return NullReturnValue;
                }
                if(EntryIsDeleted(*entry)) {
                        // value is deleted
                } else if(EntryGetHash(self, *entry) == hash) {
                        if(KeysEqual(self, GetKey(EntryGetValue(*entry)), key)) {
                                // found the value
-                               return EntryGetValue(*entry);
+                               return GetInsertReturnValue(*entry, 1);
                        }
                }
 
@@ -461,11 +469,11 @@ ValueType hashset_find(const HashSet *self, ConstKeyType key)
  */
 void hashset_remove(HashSet *self, ConstKeyType key)
 {
-       size_t num_probes = 0;
-       size_t num_buckets = self->num_buckets;
-       size_t hashmask = num_buckets - 1;
-       unsigned hash = Hash(self, key);
-       size_t bucknum = hash & hashmask;
+       size_t   num_probes  = 0;
+       size_t   num_buckets = self->num_buckets;
+       size_t   hashmask    = num_buckets - 1;
+       unsigned hash        = Hash(self, key);
+       size_t   bucknum     = hash & hashmask;
 
 #ifndef NDEBUG
        self->entries_version++;
@@ -504,12 +512,12 @@ void init_size(HashSet *self, size_t initial_size)
        if(initial_size < 4)
                initial_size = 4;
 
-       self->entries = Alloc(initial_size);
+       self->entries         = Alloc(initial_size);
        SetRangeEmpty(self->entries, initial_size);
-       self->num_buckets = initial_size;
+       self->num_buckets     = initial_size;
        self->consider_shrink = 0;
-       self->num_elements = 0;
-       self->num_deleted = 0;
+       self->num_elements    = 0;
+       self->num_deleted     = 0;
 #ifndef NDEBUG
        self->entries_version = 0;
 #endif
@@ -551,7 +559,7 @@ void hashset_init_size(HashSet *self, size_t expected_elements)
        }
 
        needed_size = expected_elements * HT_1_DIV_OCCUPANCY_FLT;
-       po2size = ceil_po2(needed_size);
+       po2size     = ceil_po2(needed_size);
        init_size(self, po2size);
 }
 
@@ -563,9 +571,9 @@ void hashset_init_size(HashSet *self, size_t expected_elements)
 void hashset_iterator_init(HashSetIterator *self, const HashSet *hashset)
 {
        self->current_bucket = hashset->entries - 1;
-       self->end = hashset->entries + hashset->num_buckets;
+       self->end            = hashset->entries + hashset->num_buckets;
 #ifndef NDEBUG
-       self->set = hashset;
+       self->set             = hashset;
        self->entries_version = hashset->entries_version;
 #endif
 }
@@ -578,7 +586,7 @@ void hashset_iterator_init(HashSetIterator *self, const HashSet *hashset)
 ValueType hashset_iterator_next(HashSetIterator *self)
 {
        HashSetEntry *current_bucket = self->current_bucket;
-       HashSetEntry *end = self->end;
+       HashSetEntry *end            = self->end;
 
        /* using hashset_insert or hashset_remove is not allowed while iterating */
        assert(self->entries_version == self->set->entries_version);
index 975557f..4f494af 100644 (file)
@@ -54,5 +54,5 @@
 
 int pset_new_contains(const pset_new_t *pset_new, const ValueType val)
 {
-       return pset_new_find(pset_new, val) != NullValue;
+       return pset_new_find(pset_new, val);
 }
index 7c228c2..5c152cf 100644 (file)
@@ -39,6 +39,9 @@
 #include "iredges_t.h"
 #include "ircons_t.h"
 #include "irgmod.h"
+#include "irnodeset.h"
+#include "irnodemap.h"
+#include "adt/cpset.h"
 
 #include "bearch_t.h"
 #include "beuses.h"
@@ -66,6 +69,7 @@ typedef struct minibelady_env_t {
        create_reload_func     create_reload;
        create_spill_func      create_spill;
        spill_info_t          *spills;
+       ir_nodemap_t           spill_infos;
 
        be_uses_t             *uses;           /**< env for the next-use magic */
 } minibelady_env_t;
@@ -81,6 +85,7 @@ block_info_t *new_block_info(struct obstack *obst, ir_node *block)
        block_info_t *res = obstack_alloc(obst, sizeof(*res));
        memset(res, 0, sizeof(res[0]));
 
+       assert(is_Block(block));
        set_irn_link(block, res);
        mark_irn_visited(block);
 
@@ -102,8 +107,8 @@ spill_info_t *create_spill_info(minibelady_env_t *env, ir_node *state)
        spill_info->value = state;
        spill_info->reloads = NEW_ARR_F(ir_node*, 0);
 
-       set_irn_link(state, spill_info);
-       mark_irn_visited(state);
+       ir_nodemap_insert(&env->spill_infos, state, spill_info);
+       //ir_fprintf(stderr, "Insert %+F -> %p\n", state, spill_info);
 
        spill_info->next = env->spills;
        env->spills = spill_info;
@@ -111,6 +116,15 @@ spill_info_t *create_spill_info(minibelady_env_t *env, ir_node *state)
        return spill_info;
 }
 
+static INLINE
+spill_info_t *get_spill_info(minibelady_env_t *env, const ir_node *node)
+{
+       spill_info_t *spill_info
+               = (spill_info_t*) ir_nodemap_get(&env->spill_infos, node);
+       //ir_fprintf(stderr, "Get %+F -> %p\n", node, spill_info);
+       return spill_info;
+}
+
 static
 spill_info_t *create_spill(minibelady_env_t *env, ir_node *state, int force)
 {
@@ -118,11 +132,8 @@ spill_info_t *create_spill(minibelady_env_t *env, ir_node *state, int force)
        ir_node *next;
        ir_node *after;
 
-       if(irn_visited(state)) {
-               spill_info = (spill_info_t*) get_irn_link(state);
-               if(spill_info->spill != NULL || !force)
-                       return spill_info;
-       } else {
+       spill_info = get_spill_info(env, state);
+       if(spill_info == NULL) {
                spill_info = create_spill_info(env, state);
        }
 
@@ -164,8 +175,8 @@ void spill_phi(minibelady_env_t *env, ir_node *phi)
        spill_info_t *spill_info;
 
        /* does a spill exist for the phis value? */
-       if(irn_visited(phi)) {
-               spill_info = (spill_info_t*) get_irn_link(phi);
+       spill_info = get_spill_info(env, phi);
+       if(spill_info != NULL) {
                spill_to_kill = spill_info->spill;
        } else {
                spill_info = create_spill_info(env, phi);
@@ -531,6 +542,7 @@ void be_assure_state(be_irg_t *birg, const arch_register_t *reg, void *func_env,
        env.lv            = be_get_birg_liveness(birg);
        env.uses          = be_begin_uses(irg, env.lv);
        env.spills        = NULL;
+       ir_nodemap_init(&env.spill_infos);
 
        assure_doms(irg);
        set_using_visited(irg);
@@ -588,6 +600,7 @@ void be_assure_state(be_irg_t *birg, const arch_register_t *reg, void *func_env,
        /* some nodes might be dead now. */
        be_remove_dead_nodes_from_schedule(birg);
 
+       ir_nodemap_destroy(&env.spill_infos);
        be_end_uses(env.uses);
        obstack_free(&env.obst, NULL);
 }
index 24c18e0..f77ad76 100644 (file)
@@ -816,7 +816,6 @@ static void ia32_perform_memory_operand(const void *self, ir_node *irn, ir_node
                set_irn_n(irn, 2, tmp);
        }
 
-       set_ia32_am_support(irn, ia32_am_Source);
        set_ia32_op_type(irn, ia32_AddrModeS);
        set_ia32_am_flavour(irn, ia32_B);
        set_ia32_ls_mode(irn, get_irn_mode(get_irn_n(irn, i)));
@@ -958,7 +957,6 @@ static void transform_to_Load(ia32_code_gen_t *cg, ir_node *node) {
        else
                new_op = new_rd_ia32_Load(dbg, irg, block, ptr, noreg, mem);
 
-       set_ia32_am_support(new_op, ia32_am_Source);
        set_ia32_op_type(new_op, ia32_AddrModeS);
        set_ia32_am_flavour(new_op, ia32_B);
        set_ia32_ls_mode(new_op, spillmode);
@@ -1033,7 +1031,6 @@ static void transform_to_Store(ia32_code_gen_t *cg, ir_node *node) {
                store = new_rd_ia32_Store(dbg, irg, block, ptr, noreg, val, nomem);
        }
 
-       set_ia32_am_support(store, ia32_am_Dest);
        set_ia32_op_type(store, ia32_AddrModeD);
        set_ia32_am_flavour(store, ia32_B);
        set_ia32_ls_mode(store, mode);
index b7db6cd..b376c86 100644 (file)
@@ -105,12 +105,12 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) {
        /* generate the add */
        if (mode_is_float(mode)) {
                res = new_rd_ia32_xAdd(dbg, irg, block, noreg, noreg, res, in1, nomem);
-               set_ia32_am_support(res, ia32_am_Source);
+               set_ia32_am_support(res, ia32_am_Source, ia32_am_binary);
                set_ia32_ls_mode(res, get_ia32_ls_mode(irn));
        }
        else {
                res = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, res, in1, nomem);
-               set_ia32_am_support(res, ia32_am_Full);
+               set_ia32_am_support(res, ia32_am_Full, ia32_am_binary);
                set_ia32_commutative(res);
        }
 
@@ -449,7 +449,6 @@ static void fix_am_source(ir_node *irn, void *env) {
                                set_ia32_ls_mode(load, ls_mode);
                                set_ia32_am_flavour(load, get_ia32_am_flavour(irn));
                                set_ia32_op_type(load, ia32_AddrModeS);
-                               set_ia32_am_support(load, ia32_am_Source);
                                set_ia32_am_scale(load, get_ia32_am_scale(irn));
                                set_ia32_am_sc(load, get_ia32_am_sc(irn));
                                add_ia32_am_offs_int(load, get_ia32_am_offs_int(irn));
index ca5018d..003216c 100644 (file)
@@ -66,7 +66,6 @@ static ir_node *create_fpu_mode_spill(void *env, ir_node *state, int force,
 
                spill = new_rd_ia32_FnstCW(NULL, irg, block, frame, noreg, state,
                                           nomem);
-               set_ia32_am_support(spill, ia32_am_Dest);
                set_ia32_op_type(spill, ia32_AddrModeD);
                set_ia32_am_flavour(spill, ia32_B);
                set_ia32_ls_mode(spill, ia32_reg_classes[CLASS_ia32_fp_cw].mode);
@@ -91,7 +90,6 @@ static ir_node *create_fpu_mode_reload(void *env, ir_node *state,
 
        if(spill != NULL) {
                reload = new_rd_ia32_FldCW(NULL, irg, block, frame, noreg, spill);
-               set_ia32_am_support(reload, ia32_am_Source);
                set_ia32_op_type(reload, ia32_AddrModeS);
                set_ia32_am_flavour(reload, ia32_B);
                set_ia32_ls_mode(reload, ia32_reg_classes[CLASS_ia32_fp_cw].mode);
@@ -107,7 +105,6 @@ static ir_node *create_fpu_mode_reload(void *env, ir_node *state,
                assert(last_state != NULL);
                cwstore = new_rd_ia32_FnstCW(NULL, irg, block, frame, noreg, last_state,
                                             nomem);
-               set_ia32_am_support(cwstore, ia32_am_Dest);
                set_ia32_op_type(cwstore, ia32_AddrModeD);
                set_ia32_am_flavour(cwstore, ia32_B);
                set_ia32_ls_mode(cwstore, lsmode);
@@ -115,7 +112,6 @@ static ir_node *create_fpu_mode_reload(void *env, ir_node *state,
                sched_add_before(before, cwstore);
 
                load = new_rd_ia32_Load(NULL, irg, block, frame, noreg, cwstore);
-               set_ia32_am_support(load, ia32_am_Source);
                set_ia32_op_type(load, ia32_AddrModeS);
                set_ia32_am_flavour(load, ia32_B);
                set_ia32_ls_mode(load, lsmode);
@@ -134,7 +130,6 @@ static ir_node *create_fpu_mode_reload(void *env, ir_node *state,
                sched_add_before(before, or);
 
                store = new_rd_ia32_Store(NULL, irg, block, frame, noreg, or, nomem);
-               set_ia32_am_support(store, ia32_am_Dest);
                set_ia32_op_type(store, ia32_AddrModeD);
                set_ia32_am_flavour(store, ia32_B);
                set_ia32_ls_mode(store, lsmode);
@@ -142,7 +137,6 @@ static ir_node *create_fpu_mode_reload(void *env, ir_node *state,
                sched_add_before(before, store);
 
                fldcw = new_rd_ia32_FldCW(NULL, irg, block, frame, noreg, store);
-               set_ia32_am_support(fldcw, ia32_am_Source);
                set_ia32_op_type(fldcw, ia32_AddrModeS);
                set_ia32_am_flavour(fldcw, ia32_B);
                set_ia32_ls_mode(fldcw, lsmode);
index fe15be5..164dfba 100644 (file)
@@ -488,12 +488,23 @@ ia32_am_type_t get_ia32_am_support(const ir_node *node) {
        return attr->data.am_support;
 }
 
+ia32_am_arity_t get_ia32_am_arity(const ir_node *node) {
+       const ia32_attr_t *attr = get_ia32_attr_const(node);
+       return attr->data.am_arity;
+}
+
 /**
  * Sets the supported address mode of an ia32 node
  */
-void set_ia32_am_support(ir_node *node, ia32_am_type_t am_tp) {
+void set_ia32_am_support(ir_node *node, ia32_am_type_t am_tp,
+                         ia32_am_arity_t arity) {
        ia32_attr_t *attr     = get_ia32_attr(node);
        attr->data.am_support = am_tp;
+       attr->data.am_arity   = arity;
+
+       assert((am_tp == ia32_am_None && arity == ia32_am_arity_none) ||
+              (am_tp != ia32_am_None &&
+              ((arity == ia32_am_unary) || (arity == ia32_am_binary))));
 }
 
 /**
index b464dbb..7389bb4 100644 (file)
@@ -84,10 +84,13 @@ void set_ia32_immop_type(ir_node *node, ia32_immop_type_t tp);
  */
 ia32_am_type_t get_ia32_am_support(const ir_node *node);
 
+ia32_am_arity_t get_ia32_am_arity(const ir_node *node);
+
 /**
  * Sets the supported addrmode of an ia32 node
  */
-void set_ia32_am_support(ir_node *node, ia32_am_type_t am_tp);
+void set_ia32_am_support(ir_node *node, ia32_am_type_t am_tp,
+                         ia32_am_arity_t am_arity);
 
 /**
  * Gets the addrmode flavour of an ia32 node
index f4daef5..653a871 100644 (file)
@@ -52,9 +52,15 @@ typedef      enum {
        ia32_am_None   = 0,   /**<< no addrmode support */
        ia32_am_Dest   = 1,   /**<< addrmode for destination only */
        ia32_am_Source = 2,   /**<< addrmode for source only */
-       ia32_am_Full   = 3    /**<< full addmode support */
+       ia32_am_Full   = 3,   /**<< full addmode support */
 } ia32_am_type_t;
 
+typedef enum {
+       ia32_am_arity_none   = 0,
+       ia32_am_unary  = 1,
+       ia32_am_binary = 2,
+} ia32_am_arity_t;
+
 /**
  * Different Address Mode properties:
  * O - Offset is set
@@ -99,16 +105,17 @@ typedef enum {
 typedef struct ia32_attr_t ia32_attr_t;
 struct ia32_attr_t {
        except_attr  exc;               /**< the exception attribute. MUST be the first one. */
-       struct {
+       struct ia32_attr_data_bitfield {
                unsigned tp:3;              /**< ia32 node type. */
                unsigned imm_tp:2;          /**< ia32 immop type. */
                unsigned am_support:2;      /**< Indicates the address mode type supported by this node. */
+               unsigned am_arity  : 2;
                unsigned am_flavour:4;      /**< The concrete address mode characteristics. */
                unsigned am_scale:2;        /**< The address mode scale for index register. */
                unsigned am_sc_sign:1;      /**< The sign bit of the address mode symconst. */
 
                unsigned use_frame:1;       /**< Indicates whether the operation uses the frame pointer or not. */
-               unsigned except_label:1;    /**< Set if this node needs a label because of posiible exception. */
+               unsigned except_label:1;    /**< Set if this node needs a label because of possible exception. */
 
                ia32_op_flavour_t op_flav:2;/**< Flavour of an op (flavour_Div/Mod/DivMod). */
 
@@ -154,6 +161,7 @@ struct ia32_attr_t {
 
        const arch_register_t **slots;     /**< register slots for assigned registers */
 };
+COMPILETIME_ASSERT(sizeof(struct ia32_attr_data_bitfield) <= 4, attr_bitfield);
 
 typedef struct ia32_immediate_attr_t ia32_immediate_attr_t;
 struct ia32_immediate_attr_t {
index dc88971..50cd0c8 100644 (file)
@@ -45,7 +45,7 @@
 
 #include "ia32_new_nodes.h"
 #include "bearch_ia32_t.h"
-#include "gen_ia32_regalloc_if_t.h"
+#include "gen_ia32_regalloc_if.h"
 #include "ia32_transform.h"
 #include "ia32_dbg_stat.h"
 #include "ia32_util.h"
@@ -311,7 +311,7 @@ static void ia32_create_Pushs(ir_node *irn, ia32_code_gen_t *cg) {
                // create a push
                push = new_rd_ia32_Push(NULL, irg, block, noreg, noreg, val, curr_sp, mem);
 
-               set_ia32_am_support(push, ia32_am_Source);
+               set_ia32_am_support(push, ia32_am_Source, ia32_am_unary);
                copy_ia32_Immop_attr(push, store);
 
                sched_add_before(irn, push);
@@ -527,7 +527,8 @@ static ia32_am_cand_t is_am_candidate(heights_t *h, const ir_node *block, ir_nod
        int      is_cand = 0, cand;
        int arity;
 
-       if (is_ia32_Ld(irn) || is_ia32_St(irn) || is_ia32_Store8Bit(irn) || is_ia32_vfild(irn) || is_ia32_vfist(irn) ||
+       if (is_ia32_Ld(irn) || is_ia32_St(irn) ||
+               is_ia32_vfild(irn) || is_ia32_vfist(irn) ||
                is_ia32_GetST0(irn) || is_ia32_SetST0(irn) || is_ia32_xStoreSimple(irn))
                return 0;
 
@@ -536,11 +537,11 @@ static ia32_am_cand_t is_am_candidate(heights_t *h, const ir_node *block, ir_nod
 
        left  = get_irn_n(irn, 2);
        arity = get_irn_arity(irn);
-       assert(arity == 5 || arity == 4);
-       if(arity == 5) {
+       if(get_ia32_am_arity(irn) == ia32_am_binary) {
                /* binary op */
                right = get_irn_n(irn, 3);
        } else {
+               assert(get_ia32_am_arity(irn) == ia32_am_unary);
                /* unary op */
                right = left;
        }
@@ -1327,6 +1328,7 @@ static void optimize_am(ir_node *irn, void *env) {
        ir_node           *addr_b, *addr_i;
        int               need_exchange_on_fail = 0;
        ia32_am_type_t    am_support;
+       ia32_am_arity_t   am_arity;
        ia32_am_cand_t cand;
        ia32_am_cand_t orig_cand;
        int               dest_possible;
@@ -1349,24 +1351,28 @@ static void optimize_am(ir_node *irn, void *env) {
                return;
 
        am_support = get_ia32_am_support(irn);
+       am_arity   = get_ia32_am_arity(irn);
        block = get_nodes_block(irn);
 
-       /* fold following patterns:                                                         */
-       /* - op -> Load into AMop with am_Source                                            */
-       /*   conditions:                                                                    */
-       /*     - op is am_Source capable AND                                                */
-       /*     - the Load is only used by this op AND                                       */
-       /*     - the Load is in the same block                                              */
-       /* - Store -> op -> Load  into AMop with am_Dest                                    */
-       /*   conditions:                                                                    */
-       /*     - op is am_Dest capable AND                                                  */
-       /*     - the Store uses the same address as the Load AND                            */
-       /*     - the Load is only used by this op AND                                       */
-       /*     - the Load and Store are in the same block AND                               */
-       /*     - nobody else uses the result of the op                                      */
-       if (get_ia32_am_support(irn) == ia32_am_None)
+       /* fold following patterns:
+        * - op -> Load into AMop with am_Source
+        *   conditions:
+        *     - op is am_Source capable AND
+        *     - the Load is only used by this op AND
+        *     - the Load is in the same block
+        * - Store -> op -> Load  into AMop with am_Dest
+        *   conditions:
+        *     - op is am_Dest capable AND
+        *     - the Store uses the same address as the Load AND
+        *     - the Load is only used by this op AND
+        *     - the Load and Store are in the same block AND
+        *     - nobody else uses the result of the op
+        */
+       if (am_support == ia32_am_None)
                return;
 
+       assert(am_arity == ia32_am_unary || am_arity == ia32_am_binary);
+
        cand = is_am_candidate(h, block, irn);
        if (cand == IA32_AM_CAND_NONE)
                return;
@@ -1376,8 +1382,7 @@ static void optimize_am(ir_node *irn, void *env) {
             cand & IA32_AM_CAND_LEFT, cand & IA32_AM_CAND_RIGHT));
 
        left  = get_irn_n(irn, 2);
-       if (get_irn_arity(irn) == 4) {
-               /* it's an "unary" operation */
+       if (am_arity == ia32_am_unary) {
                right = left;
                assert(cand == IA32_AM_CAND_BOTH);
        } else {
@@ -1491,7 +1496,7 @@ static void optimize_am(ir_node *irn, void *env) {
                        set_ia32_am_sc_sign(irn);
 
                /* connect to Load memory and disconnect Load */
-               if (get_irn_arity(irn) == 5) {
+               if (am_arity == ia32_am_binary) {
                        /* binary AMop */
                        set_irn_n(irn, 4, get_irn_n(load, 2));
                        set_irn_n(irn, 2, ia32_get_admissible_noreg(cg, irn, 2));
@@ -1579,12 +1584,11 @@ static void optimize_am(ir_node *irn, void *env) {
                }
 
                /* connect to Load memory and disconnect Load */
-               if (get_irn_arity(irn) == 5) {
+               if (am_arity == ia32_am_binary) {
                        /* binary AMop */
                        set_irn_n(irn, 3, ia32_get_admissible_noreg(cg, irn, 3));
                        set_irn_n(irn, 4, get_irn_n(load, 2));
                } else {
-                       assert(get_irn_arity(irn) == 4);
                        /* unary AMop */
                        set_irn_n(irn, 2, ia32_get_admissible_noreg(cg, irn, 2));
                        set_irn_n(irn, 3, get_irn_n(load, 2));
index a9462e0..ffcb5e7 100644 (file)
@@ -1410,7 +1410,8 @@ vfCMov => {
 
 vfadd => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
+       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp" ] },
+       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -1419,7 +1420,8 @@ vfadd => {
 
 vfmul => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
+       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp" ] },
+       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -1434,7 +1436,8 @@ l_vfmul => {
 
 vfsub => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
+       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp" ] },
+       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -1447,7 +1450,8 @@ l_vfsub => {
 },
 
 vfdiv => {
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp", "none" ] },
+       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp", "none" ] },
+       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
        outs      => [ "res", "M" ],
        latency   => 20,
        units     => [ "VFP" ],
@@ -1461,7 +1465,8 @@ l_vfdiv => {
 },
 
 vfprem => {
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
+       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp" ] },
+       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
        latency   => 20,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -1476,6 +1481,7 @@ l_vfprem => {
 vfabs => {
        irn_flags => "R",
        reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
+       ins       => [ "value" ],
        latency   => 2,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -1485,39 +1491,13 @@ vfabs => {
 vfchs => {
        irn_flags => "R",
        reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
+       ins       => [ "value" ],
        latency   => 2,
        units     => [ "VFP" ],
        mode      => "mode_E",
        attr_type => "ia32_x87_attr_t",
 },
 
-vfsin => {
-       irn_flags => "R",
-       reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
-       latency   => 150,
-       units     => [ "VFP" ],
-       mode      => "mode_E",
-       attr_type => "ia32_x87_attr_t",
-},
-
-vfcos => {
-       irn_flags => "R",
-       reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
-       latency   => 150,
-       units     => [ "VFP" ],
-       mode      => "mode_E",
-       attr_type => "ia32_x87_attr_t",
-},
-
-vfsqrt => {
-       irn_flags => "R",
-       reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
-       latency   => 30,
-       units     => [ "VFP" ],
-       mode      => "mode_E",
-       attr_type => "ia32_x87_attr_t",
-},
-
 # virtual Load and Store
 
 vfld => {
@@ -1552,6 +1532,7 @@ vfild => {
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
        outs      => [ "res", "M" ],
+       ins       => [ "base", "index", "mem" ],
        latency   => 4,
        units     => [ "VFP" ],
        attr_type => "ia32_x87_attr_t",
@@ -1566,6 +1547,7 @@ l_vfild => {
 vfist => {
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "vfp", "fpcw", "none" ] },
+       ins       => [ "base", "index", "val", "fpcw", "mem" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_M",
@@ -1814,30 +1796,6 @@ fchs => {
        attr_type => "ia32_x87_attr_t",
 },
 
-fsin => {
-       op_flags  => "R",
-       rd_constructor => "NONE",
-       reg_req   => { },
-       emit      => '. fsin',
-       attr_type => "ia32_x87_attr_t",
-},
-
-fcos => {
-       op_flags  => "R",
-       rd_constructor => "NONE",
-       reg_req   => { },
-       emit      => '. fcos',
-       attr_type => "ia32_x87_attr_t",
-},
-
-fsqrt => {
-       op_flags  => "R",
-       rd_constructor => "NONE",
-       reg_req   => { },
-       emit      => '. fsqrt $',
-       attr_type => "ia32_x87_attr_t",
-},
-
 # x87 Load and Store
 
 fld => {
index d58c25a..f9f3846 100644 (file)
@@ -95,6 +95,10 @@ typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg,
         ir_node *block, ir_node *base, ir_node *index, ir_node *op1,
         ir_node *op2, ir_node *mem);
 
+typedef ir_node *construct_binop_float_func(dbg_info *db, ir_graph *irg,
+        ir_node *block, ir_node *base, ir_node *index, ir_node *op1,
+        ir_node *op2, ir_node *mem, ir_node *fpcw);
+
 typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg,
         ir_node *block, ir_node *base, ir_node *index, ir_node *op,
         ir_node *mem);
@@ -284,7 +288,6 @@ static ir_node *gen_Const(ir_node *node) {
                                floatent = get_entity_for_tv(env_cg, node);
 
                                load     = new_rd_ia32_vfld(dbgi, irg, block, noreg, noreg, nomem, mode);
-                               set_ia32_am_support(load, ia32_am_Source);
                                set_ia32_op_type(load, ia32_AddrModeS);
                                set_ia32_am_flavour(load, ia32_am_N);
                                set_ia32_am_sc(load, floatent);
@@ -296,7 +299,6 @@ static ir_node *gen_Const(ir_node *node) {
                        floatent = get_entity_for_tv(env_cg, node);
 
                        load     = new_rd_ia32_xLoad(dbgi, irg, block, noreg, noreg, nomem);
-                       set_ia32_am_support(load, ia32_am_Source);
                        set_ia32_op_type(load, ia32_AddrModeS);
                        set_ia32_am_flavour(load, ia32_am_N);
                        set_ia32_am_sc(load, floatent);
@@ -371,49 +373,6 @@ static ir_node *gen_SymConst(ir_node *node) {
        return cnst;
 }
 
-#if 0
-/**
- * SSE convert of an integer node into a floating point node.
- */
-static ir_node *gen_sse_conv_int2float(ia32_code_gen_t *cg, dbg_info *dbgi,
-                                       ir_graph *irg, ir_node *block,
-                                       ir_node *in, ir_node *old_node, ir_mode *tgt_mode)
-{
-       ir_node *noreg    = ia32_new_NoReg_gp(cg);
-       ir_node *nomem    = new_rd_NoMem(irg);
-       ir_node *old_pred = get_Cmp_left(old_node);
-       ir_mode *in_mode  = get_irn_mode(old_pred);
-       int     in_bits   = get_mode_size_bits(in_mode);
-       ir_node *conv     = new_rd_ia32_Conv_I2FP(dbgi, irg, block, noreg, noreg, in, nomem);
-
-       set_ia32_ls_mode(conv, tgt_mode);
-       if (in_bits == 32) {
-               set_ia32_am_support(conv, ia32_am_Source);
-       }
-       SET_IA32_ORIG_NODE(conv, ia32_get_old_node_name(cg, old_node));
-
-       return conv;
-}
-
-/**
- * SSE convert of an float node into a double node.
- */
-static ir_node *gen_sse_conv_f2d(ia32_code_gen_t *cg, dbg_info *dbgi,
-                                 ir_graph *irg, ir_node *block,
-                                 ir_node *in, ir_node *old_node)
-{
-       ir_node *noreg = ia32_new_NoReg_gp(cg);
-       ir_node *nomem = new_rd_NoMem(irg);
-       ir_node *conv  = new_rd_ia32_Conv_FP2FP(dbgi, irg, block, noreg, noreg, in, nomem);
-
-       set_ia32_am_support(conv, ia32_am_Source);
-       set_ia32_ls_mode(conv, mode_xmm);
-       SET_IA32_ORIG_NODE(conv, ia32_get_old_node_name(cg, old_node));
-
-       return conv;
-}
-#endif
-
 /* Generates an entity for a known FP const (used for FP Neg + Abs) */
 ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct) {
        static const struct {
@@ -520,7 +479,8 @@ static void fold_immediate(ir_node *node, int in1, int in2) {
        }
 
        clear_ia32_commutative(node);
-       set_ia32_am_support(node, get_ia32_am_support(node) & ~ia32_am_Source);
+       set_ia32_am_support(node, get_ia32_am_support(node) & ~ia32_am_Source,
+                           get_ia32_am_arity(node));
 }
 
 /**
@@ -566,9 +526,9 @@ static ir_node *gen_binop(ir_node *node, ir_node *op1, ir_node *op2,
 
        new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, new_op1, new_op2, nomem);
        if (func == new_rd_ia32_IMul) {
-               set_ia32_am_support(new_node, ia32_am_Source);
+               set_ia32_am_support(new_node, ia32_am_Source, ia32_am_binary);
        } else {
-               set_ia32_am_support(new_node, ia32_am_Full);
+               set_ia32_am_support(new_node, ia32_am_Full, ia32_am_binary);
        }
 
        SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
@@ -587,8 +547,8 @@ static ir_node *gen_binop(ir_node *node, ir_node *op1, ir_node *op2,
  * @param func  The node constructor function
  * @return The constructed ia32 node.
  */
-static ir_node *gen_binop_float(ir_node *node, ir_node *op1, ir_node *op2,
-                                construct_binop_func *func)
+static ir_node *gen_binop_sse_float(ir_node *node, ir_node *op1, ir_node *op2,
+                                    construct_binop_func *func)
 {
        ir_node  *block    = be_transform_node(get_nodes_block(node));
        ir_node  *new_op1  = be_transform_node(op1);
@@ -600,8 +560,9 @@ static ir_node *gen_binop_float(ir_node *node, ir_node *op1, ir_node *op2,
        ir_node  *noreg_gp = ia32_new_NoReg_gp(env_cg);
        ir_node  *nomem    = new_NoMem();
 
-       new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, new_op1, new_op2, nomem);
-       set_ia32_am_support(new_node, ia32_am_Source);
+       new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, new_op1, new_op2,
+                       nomem);
+       set_ia32_am_support(new_node, ia32_am_Source, ia32_am_binary);
        if (is_op_commutative(get_irn_op(node))) {
                set_ia32_commutative(new_node);
        }
@@ -614,6 +575,43 @@ static ir_node *gen_binop_float(ir_node *node, ir_node *op1, ir_node *op2,
        return new_node;
 }
 
+/**
+ * Construct a standard binary operation, set AM and immediate if required.
+ *
+ * @param op1   The first operand
+ * @param op2   The second operand
+ * @param func  The node constructor function
+ * @return The constructed ia32 node.
+ */
+static ir_node *gen_binop_x87_float(ir_node *node, ir_node *op1, ir_node *op2,
+                                    construct_binop_float_func *func)
+{
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *new_op1  = be_transform_node(op1);
+       ir_node  *new_op2  = be_transform_node(op2);
+       ir_node  *new_node = NULL;
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       ir_graph *irg      = current_ir_graph;
+       ir_mode  *mode     = get_irn_mode(node);
+       ir_node  *noreg_gp = ia32_new_NoReg_gp(env_cg);
+       ir_node  *nomem    = new_NoMem();
+       ir_node  *fpcw     = be_abi_get_ignore_irn(env_cg->birg->abi,
+                                                  &ia32_fp_cw_regs[REG_FPCW]);
+
+       new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, new_op1, new_op2,
+                       nomem, fpcw);
+       set_ia32_am_support(new_node, ia32_am_Source, ia32_am_binary);
+       if (is_op_commutative(get_irn_op(node))) {
+               set_ia32_commutative(new_node);
+       }
+       if (USE_SSE2(env_cg)) {
+               set_ia32_ls_mode(new_node, mode);
+       }
+
+       SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
+
+       return new_node;
+}
 
 /**
  * Construct a shift/rotate binary operation, sets AM and immediate if required.
@@ -646,7 +644,7 @@ static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
        new_op = func(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
 
        /* set AM support */
-       set_ia32_am_support(new_op, ia32_am_Dest);
+       set_ia32_am_support(new_op, ia32_am_Dest, ia32_am_binary);
 
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
 
@@ -675,7 +673,7 @@ static ir_node *gen_unop(ir_node *node, ir_node *op, construct_unop_func *func)
 
        new_node = func(dbgi, irg, block, noreg, noreg, new_op, nomem);
        DB((dbg, LEVEL_1, "INT unop ..."));
-       set_ia32_am_support(new_node, ia32_am_Dest);
+       set_ia32_am_support(new_node, ia32_am_Dest, ia32_am_unary);
 
        SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
 
@@ -711,9 +709,9 @@ static ir_node *gen_Add(ir_node *node) {
        if (mode_is_float(mode)) {
                FP_USED(env_cg);
                if (USE_SSE2(env_cg))
-                       return gen_binop_float(node, op1, op2, new_rd_ia32_xAdd);
+                       return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xAdd);
                else
-                       return gen_binop_float(node, op1, op2, new_rd_ia32_vfadd);
+                       return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfadd);
        }
 
        /* integer ADD */
@@ -734,7 +732,6 @@ static ir_node *gen_Add(ir_node *node) {
                        new_op = new_rd_ia32_Lea(dbgi, irg, block, new_op1, noreg);
                        set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op2));
                        set_ia32_am_flavour(new_op, ia32_am_B);
-                       set_ia32_am_support(new_op, ia32_am_Source);
                        set_ia32_op_type(new_op, ia32_AddrModeS);
 
                        DBG_OPT_LEA3(new_op1, new_op2, node, new_op);
@@ -749,7 +746,6 @@ static ir_node *gen_Add(ir_node *node) {
                        set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op1));
                        add_ia32_am_offs_int(new_op, offs);
                        set_ia32_am_flavour(new_op, ia32_am_OB);
-                       set_ia32_am_support(new_op, ia32_am_Source);
                        set_ia32_op_type(new_op, ia32_AddrModeS);
                } else if (tp2 == ia32_ImmSymConst) {
                        tarval *tv = get_ia32_Immop_tarval(new_op1);
@@ -762,7 +758,6 @@ static ir_node *gen_Add(ir_node *node) {
                        add_ia32_am_offs_int(new_op, offs);
                        set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op2));
                        set_ia32_am_flavour(new_op, ia32_am_OB);
-                       set_ia32_am_support(new_op, ia32_am_Source);
                        set_ia32_op_type(new_op, ia32_AddrModeS);
                } else {
                        tarval *tv1 = get_ia32_Immop_tarval(new_op1);
@@ -805,7 +800,7 @@ static ir_node *gen_Add(ir_node *node) {
        new_op = new_rd_ia32_Add(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
 
        /* set AM support */
-       set_ia32_am_support(new_op, ia32_am_Full);
+       set_ia32_am_support(new_op, ia32_am_Full, ia32_am_binary);
        set_ia32_commutative(new_op);
 
        fold_immediate(new_op, 2, 3);
@@ -830,7 +825,7 @@ static ir_node *create_ia32_Mul(ir_node *node) {
 
        res = new_rd_ia32_Mul(dbgi, irg, block, noreg, noreg, new_op1, new_op2, new_NoMem());
        set_ia32_commutative(res);
-       set_ia32_am_support(res, ia32_am_Source);
+       set_ia32_am_support(res, ia32_am_Source | ia32_am_binary);
 
        /* imediates are not supported, so no fold_immediate */
        proj_EAX = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_EAX);
@@ -858,9 +853,9 @@ static ir_node *gen_Mul(ir_node *node) {
        if (mode_is_float(mode)) {
                FP_USED(env_cg);
                if (USE_SSE2(env_cg))
-                       return gen_binop_float(node, op1, op2, new_rd_ia32_xMul);
+                       return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xMul);
                else
-                       return gen_binop_float(node, op1, op2, new_rd_ia32_vfmul);
+                       return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfmul);
        }
 
        /*
@@ -899,9 +894,7 @@ static ir_node *gen_Mulh(ir_node *node) {
        }
 
        set_ia32_commutative(res);
-       set_ia32_am_support(res, ia32_am_Source);
-
-       set_ia32_am_support(res, ia32_am_Source);
+       set_ia32_am_support(res, ia32_am_Source, ia32_am_binary);
 
        proj_EAX = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_EAX);
        proj_EDX = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_EDX);
@@ -982,7 +975,7 @@ static ir_node *gen_Max(ir_node *node) {
        if (mode_is_float(mode)) {
                FP_USED(env_cg);
                if (USE_SSE2(env_cg)) {
-                       new_op = gen_binop_float(node, new_op1, new_op2, new_rd_ia32_xMax);
+                       new_op = gen_binop_sse_float(node, new_op1, new_op2, new_rd_ia32_xMax);
                } else {
                        panic("Can't create Max node");
                }
@@ -1021,7 +1014,7 @@ static ir_node *gen_Min(ir_node *node) {
        if (mode_is_float(mode)) {
                FP_USED(env_cg);
                if (USE_SSE2(env_cg)) {
-                       new_op = gen_binop_float(node, op1, op2, new_rd_ia32_xMin);
+                       new_op = gen_binop_sse_float(node, op1, op2, new_rd_ia32_xMin);
                } else {
                        panic("can't create Min node");
                }
@@ -1068,9 +1061,9 @@ static ir_node *gen_Sub(ir_node *node) {
        if (mode_is_float(mode)) {
                FP_USED(env_cg);
                if (USE_SSE2(env_cg))
-                       return gen_binop_float(node, op1, op2, new_rd_ia32_xSub);
+                       return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xSub);
                else
-                       return gen_binop_float(node, op1, op2, new_rd_ia32_vfsub);
+                       return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfsub);
        }
 
        /* integer SUB */
@@ -1104,7 +1097,6 @@ static ir_node *gen_Sub(ir_node *node) {
                        set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op1));
                        add_ia32_am_offs_int(new_op, -offs);
                        set_ia32_am_flavour(new_op, ia32_am_OB);
-                       set_ia32_am_support(new_op, ia32_am_Source);
                        set_ia32_op_type(new_op, ia32_AddrModeS);
                } else if (tp2 == ia32_ImmSymConst) {
                        tarval *tv = get_ia32_Immop_tarval(new_op1);
@@ -1118,7 +1110,6 @@ static ir_node *gen_Sub(ir_node *node) {
                        set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op2));
                        set_ia32_am_sc_sign(new_op);
                        set_ia32_am_flavour(new_op, ia32_am_OB);
-                       set_ia32_am_support(new_op, ia32_am_Source);
                        set_ia32_op_type(new_op, ia32_AddrModeS);
                } else {
                        tarval *tv1 = get_ia32_Immop_tarval(new_op1);
@@ -1161,7 +1152,7 @@ static ir_node *gen_Sub(ir_node *node) {
        new_op = new_rd_ia32_Sub(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
 
        /* set AM support */
-       set_ia32_am_support(new_op, ia32_am_Full);
+       set_ia32_am_support(new_op, ia32_am_Full, ia32_am_binary);
 
        fold_immediate(new_op, 2, 3);
 
@@ -1251,7 +1242,7 @@ static ir_node *generate_DivMod(ir_node *node, ir_node *dividend,
        /* Matze: code can't handle this at the moment... */
 #if 0
        /* set AM support */
-       set_ia32_am_support(res, ia32_am_Source);
+       set_ia32_am_support(res, ia32_am_Source, ia32_am_binary);
 #endif
 
        /* check, which Proj-Keep, we need to add */
@@ -1325,18 +1316,21 @@ static ir_node *gen_Quot(ir_node *node) {
                ir_mode *mode = get_irn_mode(op1);
                if (is_ia32_xConst(new_op2)) {
                        new_op = new_rd_ia32_xDiv(dbgi, irg, block, noreg, noreg, new_op1, noreg, nomem);
-                       set_ia32_am_support(new_op, ia32_am_None);
+                       set_ia32_am_support(new_op, ia32_am_None, ia32_am_arity_none);
                        copy_ia32_Immop_attr(new_op, new_op2);
                } else {
                        new_op = new_rd_ia32_xDiv(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
                        // Matze: disabled for now, spillslot coalescer fails
-                       //set_ia32_am_support(new_op, ia32_am_Source);
+                       //set_ia32_am_support(new_op, ia32_am_Source | ia32_am_binary);
                }
                set_ia32_ls_mode(new_op, mode);
        } else {
-               new_op = new_rd_ia32_vfdiv(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
+               ir_node  *fpcw = be_abi_get_ignore_irn(env_cg->birg->abi,
+                                                      &ia32_fp_cw_regs[REG_FPCW]);
+               new_op = new_rd_ia32_vfdiv(dbgi, irg, block, noreg, noreg, new_op1,
+                                          new_op2, nomem, fpcw);
                // Matze: disabled for now (spillslot coalescer fails)
-               //set_ia32_am_support(new_op, ia32_am_Source);
+               //set_ia32_am_support(new_op, ia32_am_Source | ia32_am_binary);
        }
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
        return new_op;
@@ -1661,7 +1655,6 @@ static ir_node *gen_Load(ir_node *node) {
        }
 
        set_irn_pinned(new_op, get_irn_pinned(node));
-       set_ia32_am_support(new_op, ia32_am_Source);
        set_ia32_op_type(new_op, ia32_AddrModeS);
        set_ia32_am_flavour(new_op, am_flav);
        set_ia32_ls_mode(new_op, mode);
@@ -1750,7 +1743,6 @@ static ir_node *gen_Store(ir_node *node) {
        }
 
        set_irn_pinned(new_op, get_irn_pinned(node));
-       set_ia32_am_support(new_op, ia32_am_Dest);
        set_ia32_op_type(new_op, ia32_AddrModeD);
        set_ia32_am_flavour(new_op, am_flav);
        set_ia32_ls_mode(new_op, mode);
@@ -1872,7 +1864,7 @@ static ir_node *gen_Cond(ir_node *node) {
                // is not able to detect the mode of the spilled value
                // moreover, the lea optimize phase freely exchanges left/right
                // without updating the pnc
-               //set_ia32_am_support(res, ia32_am_Source);
+               //set_ia32_am_support(res, ia32_am_Source | ia32_am_binary);
        }
        else {
                /* determine the smallest switch case value */
@@ -1891,7 +1883,6 @@ static ir_node *gen_Cond(ir_node *node) {
                        SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
                        add_ia32_am_offs_int(res, -switch_min);
                        set_ia32_am_flavour(res, ia32_am_OB);
-                       set_ia32_am_support(res, ia32_am_Source);
                        set_ia32_op_type(res, ia32_AddrModeS);
                }
 
@@ -2123,7 +2114,6 @@ static ir_node *gen_x87_fp_to_gp(ir_node *node) {
 
        set_irn_pinned(fist, op_pin_state_floats);
        set_ia32_use_frame(fist);
-       set_ia32_am_support(fist, ia32_am_Dest);
        set_ia32_op_type(fist, ia32_AddrModeD);
        set_ia32_am_flavour(fist, ia32_am_B);
        set_ia32_ls_mode(fist, mode_Iu);
@@ -2134,7 +2124,6 @@ static ir_node *gen_x87_fp_to_gp(ir_node *node) {
 
        set_irn_pinned(load, op_pin_state_floats);
        set_ia32_use_frame(load);
-       set_ia32_am_support(load, ia32_am_Source);
        set_ia32_op_type(load, ia32_AddrModeS);
        set_ia32_am_flavour(load, ia32_am_B);
        set_ia32_ls_mode(load, mode_Iu);
@@ -2161,12 +2150,12 @@ static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode) {
        src_bits = get_mode_size_bits(src_mode);
        if (src_bits == 8) {
                new_op = new_rd_ia32_Conv_I2I8Bit(dbgi, irg, block, noreg, noreg, new_op, nomem);
-               set_ia32_am_support(new_op, ia32_am_Source);
+               set_ia32_am_support(new_op, ia32_am_Source, ia32_am_unary);
                set_ia32_ls_mode(new_op, src_mode);
                SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
        } else if (src_bits < 32) {
                new_op = new_rd_ia32_Conv_I2I(dbgi, irg, block, noreg, noreg, new_op, nomem);
-               set_ia32_am_support(new_op, ia32_am_Source);
+               set_ia32_am_support(new_op, ia32_am_Source, ia32_am_unary);
                set_ia32_ls_mode(new_op, src_mode);
                SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
        }
@@ -2175,7 +2164,6 @@ static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode) {
        store = new_rd_ia32_Store(dbgi, irg, block, get_irg_frame(irg), noreg, new_op, nomem);
 
        set_ia32_use_frame(store);
-       set_ia32_am_support(store, ia32_am_Dest);
        set_ia32_op_type(store, ia32_AddrModeD);
        set_ia32_am_flavour(store, ia32_am_OB);
        set_ia32_ls_mode(store, mode_Iu);
@@ -2184,7 +2172,6 @@ static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode) {
        fild = new_rd_ia32_vfild(dbgi, irg, block, get_irg_frame(irg), noreg, store);
 
        set_ia32_use_frame(fild);
-       set_ia32_am_support(fild, ia32_am_Source);
        set_ia32_op_type(fild, ia32_AddrModeS);
        set_ia32_am_flavour(fild, ia32_am_OB);
        set_ia32_ls_mode(fild, mode_Iu);
@@ -2215,14 +2202,12 @@ static ir_node *create_Strict_conv(ir_mode *src_mode, ir_mode *tgt_mode,
        store = new_rd_ia32_vfst(dbgi, irg, block, frame, noreg, node, nomem,
                                 smaller_mode);
        set_ia32_use_frame(store);
-       set_ia32_am_support(store, ia32_am_Dest);
        set_ia32_op_type(store, ia32_AddrModeD);
        set_ia32_am_flavour(store, ia32_am_OB);
 
        load = new_rd_ia32_vfld(dbgi, irg, block, frame, noreg, store,
                                smaller_mode);
        set_ia32_use_frame(load);
-       set_ia32_am_support(load, ia32_am_Source);
        set_ia32_op_type(load, ia32_AddrModeS);
        set_ia32_am_flavour(load, ia32_am_OB);
 
@@ -2307,7 +2292,7 @@ static ir_node *gen_Conv(ir_node *node) {
                                res = new_rd_ia32_Conv_I2FP(dbgi, irg, block, noreg, noreg, new_op, nomem);
                                set_ia32_ls_mode(res, tgt_mode);
                                if(src_bits == 32) {
-                                       set_ia32_am_support(res, ia32_am_Source);
+                                       set_ia32_am_support(res, ia32_am_Source, ia32_am_unary);
                                }
                        } else {
                                return gen_x87_gp_to_fp(node, src_mode);
@@ -2338,7 +2323,7 @@ static ir_node *gen_Conv(ir_node *node) {
                                res = new_rd_ia32_Conv_I2I(dbgi, irg, block, noreg, noreg, new_op, nomem);
                                set_ia32_ls_mode(res, smaller_mode);
                        }
-                       set_ia32_am_support(res, ia32_am_Source);
+                       set_ia32_am_support(res, ia32_am_Source, ia32_am_unary);
                }
        }
 
@@ -2892,7 +2877,6 @@ static ir_node *gen_be_StackParam(ir_node *node) {
        set_ia32_frame_ent(new_op, ent);
        set_ia32_use_frame(new_op);
 
-       set_ia32_am_support(new_op, ia32_am_Source);
        set_ia32_op_type(new_op, ia32_AddrModeS);
        set_ia32_am_flavour(new_op, ia32_am_B);
        set_ia32_ls_mode(new_op, load_mode);
@@ -2917,7 +2901,6 @@ static ir_node *gen_be_FrameAddr(ir_node *node) {
 
        res = new_rd_ia32_Lea(dbgi, irg, block, new_op, noreg);
        set_ia32_frame_ent(res, arch_get_frame_entity(env_cg->arch_env, node));
-       set_ia32_am_support(res, ia32_am_Full);
        set_ia32_use_frame(res);
        set_ia32_am_flavour(res, ia32_am_OB);
 
@@ -2962,7 +2945,6 @@ static ir_node *gen_be_FrameLoad(ir_node *node) {
        set_ia32_frame_ent(new_op, ent);
        set_ia32_use_frame(new_op);
 
-       set_ia32_am_support(new_op, ia32_am_Source);
        set_ia32_op_type(new_op, ia32_AddrModeS);
        set_ia32_am_flavour(new_op, ia32_am_B);
        set_ia32_ls_mode(new_op, mode);
@@ -3008,7 +2990,6 @@ static ir_node *gen_be_FrameStore(ir_node *node) {
        set_ia32_frame_ent(new_op, ent);
        set_ia32_use_frame(new_op);
 
-       set_ia32_am_support(new_op, ia32_am_Dest);
        set_ia32_op_type(new_op, ia32_AddrModeD);
        set_ia32_am_flavour(new_op, ia32_am_B);
        set_ia32_ls_mode(new_op, mode);
@@ -3082,7 +3063,6 @@ static ir_node *gen_be_Return(ir_node *node) {
        set_ia32_op_type(sse_store, ia32_AddrModeD);
        set_ia32_use_frame(sse_store);
        set_ia32_am_flavour(sse_store, ia32_am_B);
-       set_ia32_am_support(sse_store, ia32_am_Dest);
 
        /* load into st0 */
        fld = new_rd_ia32_SetST0(dbgi, irg, block, frame, noreg, sse_store);
@@ -3090,7 +3070,6 @@ static ir_node *gen_be_Return(ir_node *node) {
        set_ia32_op_type(fld, ia32_AddrModeS);
        set_ia32_use_frame(fld);
        set_ia32_am_flavour(fld, ia32_am_B);
-       set_ia32_am_support(fld, ia32_am_Source);
 
        mproj = new_r_Proj(irg, block, fld, mode_M, pn_ia32_SetST0_M);
        fld   = new_r_Proj(irg, block, fld, mode_vfp, pn_ia32_SetST0_res);
@@ -3148,7 +3127,7 @@ static ir_node *gen_be_AddSP(ir_node *node) {
        /* ia32 stack grows in reverse direction, make a SubSP */
        new_op = new_rd_ia32_SubSP(dbgi, irg, block, noreg, noreg, new_sp, new_sz,
                                   nomem);
-       set_ia32_am_support(new_op, ia32_am_Source);
+       set_ia32_am_support(new_op, ia32_am_Source, ia32_am_binary);
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
 
        return new_op;
@@ -3176,7 +3155,7 @@ static ir_node *gen_be_SubSP(ir_node *node) {
 
        /* ia32 stack grows in reverse direction, make an AddSP */
        new_op = new_rd_ia32_AddSP(dbgi, irg, block, noreg, noreg, new_sp, new_sz, nomem);
-       set_ia32_am_support(new_op, ia32_am_Source);
+       set_ia32_am_support(new_op, ia32_am_Source, ia32_am_binary);
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
 
        return new_op;
@@ -3284,7 +3263,6 @@ static ir_node *gen_lowered_Load(ir_node *node, construct_load_func func, char f
 
        new_op  = func(dbgi, irg, block, new_ptr, noreg, new_mem);
 
-       set_ia32_am_support(new_op, ia32_am_Source);
        set_ia32_op_type(new_op, ia32_AddrModeS);
        set_ia32_am_flavour(new_op, ia32_am_OB);
        set_ia32_am_offs_int(new_op, 0);
@@ -3339,7 +3317,6 @@ static ir_node *gen_lowered_Store(ir_node *node, construct_store_func func, char
                add_ia32_am_offs_int(new_op, am_offs);
        }
 
-       set_ia32_am_support(new_op, ia32_am_Dest);
        set_ia32_op_type(new_op, ia32_AddrModeD);
        set_ia32_am_flavour(new_op, am_flav);
        set_ia32_ls_mode(new_op, mode);
@@ -3368,11 +3345,11 @@ static ir_node *gen_lowered_Store(ir_node *node, construct_store_func func, char
        }
 
 #define GEN_LOWERED_x87_OP(op)                                                 \
-       static ir_node *gen_ia32_l_##op(ir_node *node) {\
+       static ir_node *gen_ia32_l_##op(ir_node *node) {                           \
                ir_node *new_op;                                                       \
-               FORCE_x87(env_cg);                                                    \
-               new_op = gen_binop_float(node, get_binop_left(node),              \
-                                        get_binop_right(node), new_rd_ia32_##op);     \
+               FORCE_x87(env_cg);                                                     \
+               new_op = gen_binop_x87_float(node, get_binop_left(node),               \
+                                            get_binop_right(node), new_rd_ia32_##op); \
                return new_op;                                                         \
        }
 
@@ -3425,11 +3402,14 @@ static ir_node *gen_ia32_l_vfdiv(ir_node *node) {
        ir_node  *noreg     = ia32_new_NoReg_gp(env_cg);
        ir_graph *irg       = current_ir_graph;
        dbg_info *dbgi      = get_irn_dbg_info(node);
+       ir_node  *fpcw      = be_abi_get_ignore_irn(env_cg->birg->abi,
+                                                   &ia32_fp_cw_regs[REG_FPCW]);
        ir_node  *vfdiv;
 
-       vfdiv = new_rd_ia32_vfdiv(dbgi, irg, block, noreg, noreg, new_left, new_right, new_NoMem());
+       vfdiv = new_rd_ia32_vfdiv(dbgi, irg, block, noreg, noreg, new_left,
+                                 new_right, new_NoMem(), fpcw);
        clear_ia32_commutative(vfdiv);
-       set_ia32_am_support(vfdiv, ia32_am_Source);
+       set_ia32_am_support(vfdiv, ia32_am_Source, ia32_am_binary);
 
        SET_IA32_ORIG_NODE(vfdiv, ia32_get_old_node_name(env_cg, node));
 
@@ -3457,9 +3437,10 @@ static ir_node *gen_ia32_l_Mul(ir_node *node) {
 
        /* l_Mul is already a mode_T node, so we create the Mul in the normal way   */
        /* and then skip the result Proj, because all needed Projs are already there. */
-       ir_node *muls = new_rd_ia32_Mul(dbgi, irg, block, noreg, noreg, new_left, new_right, new_NoMem());
+       ir_node *muls = new_rd_ia32_Mul(dbgi, irg, block, noreg, noreg, new_left,
+                                       new_right, new_NoMem());
        clear_ia32_commutative(muls);
-       set_ia32_am_support(muls, ia32_am_Source);
+       set_ia32_am_support(muls, ia32_am_Source, ia32_am_binary);
 
        /* check if EAX and EDX proj exist, add missing one */
        in[0] = new_rd_Proj(dbgi, irg, block, muls, mode_Iu, pn_EAX);
@@ -3541,8 +3522,7 @@ static ir_node *gen_lowered_64bit_shifts(ir_node *node, ir_node *op1,
        }
 
        /* set AM support */
-       // Matze: node has unsupported format (6inputs)
-       //set_ia32_am_support(new_op, ia32_am_Dest);
+       set_ia32_am_support(new_op, ia32_am_Dest, ia32_am_binary);
 
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
 
@@ -3591,7 +3571,6 @@ static ir_node *gen_ia32_l_X87toSSE(ir_node *node) {
        set_ia32_frame_ent(res, get_ia32_frame_ent(node));
        set_ia32_use_frame(res);
        set_ia32_ls_mode(res, get_ia32_ls_mode(node));
-       set_ia32_am_support(res, ia32_am_Dest);
        set_ia32_am_flavour(res, ia32_B);
        set_ia32_op_type(res, ia32_AddrModeD);
 
@@ -3600,7 +3579,6 @@ static ir_node *gen_ia32_l_X87toSSE(ir_node *node) {
        set_ia32_frame_ent(res, get_ia32_frame_ent(node));
        set_ia32_use_frame(res);
        set_ia32_ls_mode(res, get_ia32_ls_mode(node));
-       set_ia32_am_support(res, ia32_am_Source);
        set_ia32_am_flavour(res, ia32_B);
        set_ia32_op_type(res, ia32_AddrModeS);
        res = new_rd_Proj(dbgi, irg, block, res, mode_xmm, pn_ia32_xLoad_res);
@@ -3650,7 +3628,6 @@ static ir_node *gen_ia32_l_SSEtoX87(ir_node *node) {
                set_ia32_frame_ent(res, fent);
                set_ia32_use_frame(res);
                set_ia32_ls_mode(res, lsmode);
-               set_ia32_am_support(res, ia32_am_Dest);
                set_ia32_am_flavour(res, ia32_B);
                set_ia32_op_type(res, ia32_AddrModeD);
                mem = res;
@@ -3661,7 +3638,6 @@ static ir_node *gen_ia32_l_SSEtoX87(ir_node *node) {
        set_ia32_frame_ent(res, fent);
        set_ia32_use_frame(res);
        add_ia32_am_offs_int(res, offs);
-       set_ia32_am_support(res, ia32_am_Source);
        set_ia32_am_flavour(res, ia32_B);
        set_ia32_op_type(res, ia32_AddrModeS);
        res = new_rd_Proj(dbgi, irg, block, res, mode_vfp, pn_ia32_vfld_res);
@@ -3980,7 +3956,6 @@ static ir_node *gen_Proj_be_Call(ir_node *node) {
                set_ia32_op_type(fstp, ia32_AddrModeD);
                set_ia32_use_frame(fstp);
                set_ia32_am_flavour(fstp, ia32_am_B);
-               set_ia32_am_support(fstp, ia32_am_Dest);
 
                /* load into SSE register */
                sse_load = new_rd_ia32_xLoad(dbgi, irg, block, frame, noreg, fstp);
@@ -3988,7 +3963,6 @@ static ir_node *gen_Proj_be_Call(ir_node *node) {
                set_ia32_op_type(sse_load, ia32_AddrModeS);
                set_ia32_use_frame(sse_load);
                set_ia32_am_flavour(sse_load, ia32_am_B);
-               set_ia32_am_support(sse_load, ia32_am_Source);
 
                sse_load = new_rd_Proj(dbgi, irg, block, sse_load, mode_xmm, pn_ia32_xLoad_res);
 
@@ -4057,10 +4031,8 @@ static ir_node *gen_Proj_Cmp(ir_node *node)
        }
        /* TODO:
         * (a == b) -> !(a ^ b)
-        * (a < 0)  -> (a & 0x80000000)
-        * (a <= 0) -> !(a & 0x7fffffff)
-        * (a > 0)  -> (a & 0x7fffffff)
-        * (a >= 0) -> !(a & 0x80000000)
+        * (a < 0)  -> (a & 0x80000000) oder a >> 31
+        * (a >= 0) -> (a >> 31) ^ 1
         */
 
        if(!mode_is_signed(cmp_mode)) {
index cb17768..79a2b06 100644 (file)
@@ -1166,8 +1166,8 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op, ir_op *op_p) {
        } else {
                op2_idx = x87_on_stack(state, op2_reg_idx);
                live_after_node = is_vfp_live(arch_register_get_index(op2), live);
-               assert(op2_idx >= 0);
                DB((dbg, LEVEL_1, ">>> %+F %s ->\n", n, arch_register_get_name(op2)));
+               assert(op2_idx >= 0);
        }
 
        mode  = get_ia32_ls_mode(n);
@@ -1288,9 +1288,6 @@ GEN_BINOP(fprem)
 
 GEN_UNOP(fabs)
 GEN_UNOP(fchs)
-GEN_UNOP(fsin)
-GEN_UNOP(fcos)
-GEN_UNOP(fsqrt)
 
 GEN_LOAD(fld)
 GEN_LOAD(fild)
@@ -2006,6 +2003,43 @@ static x87_state *x87_kill_deads(x87_simulator *sim, ir_node *block, x87_state *
        return state;
 }  /* x87_kill_deads */
 
+/**
+ * If we have PhiEs with unknown operands then we have to make sure that some
+ * value is actually put onto the stack.
+ */
+static void fix_unknown_phis(x87_state *state, ir_node *block,
+                             ir_node *pred_block, int pos)
+{
+       ir_node *node;
+
+       sched_foreach(block, node) {
+               ir_node               *zero;
+               const arch_register_t *reg;
+               ia32_x87_attr_t       *attr;
+
+               if(!is_Phi(node))
+                       break;
+
+               ir_node *op = get_Phi_pred(node, pos);
+               if(!is_ia32_Unknown_VFP(op))
+                       continue;
+
+               reg = arch_get_irn_register(state->sim->arch_env, node);
+
+               /* create a zero at end of pred block */
+               zero = new_rd_ia32_fldz(NULL, current_ir_graph, pred_block, mode_E);
+               x87_push(state, arch_register_get_index(reg), zero);
+
+               attr = get_ia32_x87_attr(zero);
+               attr->x87[2] = &ia32_st_regs[0];
+
+               assert(is_ia32_fldz(zero));
+               sched_add_before(sched_last(pred_block), zero);
+
+               set_Phi_pred(node, pos, zero);
+       }
+}
+
 /**
  * Run a simulation and fix all virtual instructions for a block.
  *
@@ -2074,8 +2108,11 @@ static void x87_simulate_block(x87_simulator *sim, ir_node *block) {
 
                succ_state = x87_get_bl_state(sim, succ);
 
+               fix_unknown_phis(state, succ, block, get_edge_src_pos(edge));
+
                if (succ_state->begin == NULL) {
                        succ_state->begin = state;
+
                        waitq_put(sim->worklist, succ);
                } else {
                        /* There is already a begin state for the successor, bad.
@@ -2128,9 +2165,6 @@ static void x87_init_simulator(x87_simulator *sim, ir_graph *irg,
        ASSOC_IA32(fprem);
        ASSOC_IA32(fabs);
        ASSOC_IA32(fchs);
-       ASSOC_IA32(fsin);
-       ASSOC_IA32(fcos);
-       ASSOC_IA32(fsqrt);
        ASSOC_IA32(fist);
        ASSOC_IA32(fst);
        ASSOC_IA32(fCondJmp);
diff --git a/ir/be/test/bad_ones b/ir/be/test/bad_ones
deleted file mode 100644 (file)
index e69de29..0000000
index f71599c..370edf2 100644 (file)
@@ -2,23 +2,8 @@
 
 const wchar_t AmmoCaliber[][20] =
 {
-       L"0",
+       L"BlupBlupBlupBlupBlup",
        L".38 Kal",
-       L"9mm",
-       L".45 Kal",
-       L".357 Kal",
-       L"12 Kal",
-       L"CAWS",
-       L"5.45mm",
-       L"5.56mm",
-       L"7.62mm NATO",
-       L"7.62mm WP",
-       L"4.7mm",
-       L"5.7mm",
-       L"Monster",
-       L"Rakete",
-       L"",
-       L"",
 };
 
 
diff --git a/ir/be/test/good_ones b/ir/be/test/good_ones
deleted file mode 100644 (file)
index d52e03a..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-Args.c
-Arrays.c
-BinaryOpTest.c
-BreakTest.c
-ByteTest.c
-CallingTest.c
-CondExpr.c
-ContinueTest.c
-DeclTest.c
-DivBug.c
-Do.c
-Doit.c
-Empty.c
-EmptyFor.c
-Field.c
-Float.c
-ForTest.c
-GlobalCseTest.c
-Hanoi.c
-HeapSort.c
-HelloWorld.c
-IfExpr.c
-Int.c
-Label.c
-Local.c
-MergeSort.c
-Or.c
-Pdg.c
-Queens.c
-QuickSort.c
-RegallocBug.c
-Return.c
-SimpleExpr.c
-Sieve.c
-SieveBits.c
-Strings.c
-Swap.c
-Switcher.c
-Test.c
-Thilo.c
-While.c
-XXEndless.c
-adam_putt.c
-addr_test.c
-alloca.c
-am_test.c
-andtest.c
-apfel.c
-array_type.c
-biggest_prime.c
-bsp.c
-callref.c
-calls.c
-cmp.c
-compress95.c
-conv.c
-convtest.c
-d.c
-dblstruct.c
-divtest.c
-duffs.c
-enum.c
-fe_bug.c
-fehler1.c
-fehler10.c
-fehler11.c
-fehler12.c
-fehler3.c
-fehler4.c
-fehler5.c
-fehler6.c
-fehler7.c
-fehler8.c
-fehler9.c
-fbench.c
-ffbench.c
-func_arg.c
-gcd.c
-harness.c
-iabs.c
-if.c
-ll_call.c
-max.c
-mul.c
-multidim-array.c
-nested_loops.c
-nested_loops2.c
-ns.c
-nullnode.c
-optest.c
-pbqp_RedN.c
-rotate.c
-simd1-i.c
-simd1.c
-simd2.c
-simple.c
-sret.c
-stmt_expr.c
-strenght_red.c
-struct.c
-structtest.c
-switch_test.c
-switch_test2.c
-tailrec.c
-trivial_add.c
-trivial_div.c
-trivial_empty.c
-trivial_extern_add.c
-trivial_max.c
-trivial_sum_upto.c
-trivial_two_times.c
-truth.c
-types.c
-types2.c
-use_uninit_ptr.c
-while-printf.c
-wrong_cmp.c
index 9ac7624..bac3fb0 100644 (file)
@@ -39,9 +39,9 @@
 #define NullValue                 NULL
 #define DeletedValue              ((ir_node*)-1)
 #ifdef DEBUG_libfirm
-#define Hash(this,value)          ((unsigned)((value)->node_nr))
+#define Hash(this,key)            ((unsigned)((key)->node_nr))
 #else
-#define Hash(this,value)          HASH_PTR(value)
+#define Hash(this,key)            HASH_PTR(key)
 #endif
 #define KeysEqual(this,key1,key2) (key1) == (key2)
 #define SetRangeEmpty(ptr,size)   memset(ptr, 0, (size) * sizeof((ptr)[0]))
@@ -66,5 +66,5 @@ void ir_nodeset_init(ir_nodeset_t *nodeset)
 
 int ir_nodeset_contains(const ir_nodeset_t *this, const ir_node *node)
 {
-       return _ir_nodeset_find(this, node) != NULL;
+       return _ir_nodeset_find(this, node);
 }
index afbfac8..56a7df8 100644 (file)
@@ -30,7 +30,7 @@
 #ifndef _FIRM_IRNODESET_H_
 #define _FIRM_IRNODESET_H_
 
-#include "irnode.h"
+#include "firm_types.h"
 #include "xmalloc.h"
 
 #define HashSet          ir_nodeset_t
@@ -43,6 +43,9 @@
 #undef HashSetIterator
 #undef HashSet
 
+typedef struct ir_nodeset_t          ir_nodeset_t;
+typedef struct ir_nodeset_iterator_t ir_nodeset_iterator_t;
+
 /**
  * Initializes a nodeset with default size.
  *
index 2b3e10c..f42c6c1 100644 (file)
@@ -182,6 +182,9 @@ static int reassoc_Sub(ir_node **in)
                DBG((dbg, LEVEL_5, "Applied: %n - %n => %n + (-%n)\n",
                        get_Sub_left(n), c, get_Sub_left(n), c));
 
+               if(n == irn)
+                       return 0;
+
                exchange(n, irn);
                *in = irn;
 
index f7a8f22..f022fd6 100644 (file)
@@ -100,6 +100,8 @@ static struct set *tarvals = NULL;   /* container for tarval structs */
 static struct set *values = NULL;    /* container for values */
 static tarval_int_overflow_mode_t int_overflow_mode = TV_OVERFLOW_WRAP;
 
+static int no_float = 1;
+
 /****************************************************************************
  *   private functions
  ****************************************************************************/
@@ -747,6 +749,8 @@ pn_Cmp tarval_cmp(tarval *a, tarval *b) {
                return pn_Cmp_False;
 
        case irms_float_number:
+               if(no_float)
+                       return pn_Cmp_False;
                /*
                 * BEWARE: we cannot compare a == b here, because
                 * a NaN is always Unordered to any other value, even to itself!
@@ -967,6 +971,9 @@ tarval *tarval_neg(tarval *a) {
                return get_tarval_overflow(buffer, a->length, a->mode);
 
        case irms_float_number:
+               if(no_float)
+                       return tarval_bad;
+
                fc_neg(a->value, NULL);
                return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode);
 
@@ -999,6 +1006,9 @@ tarval *tarval_add(tarval *a, tarval *b) {
                return get_tarval_overflow(buffer, a->length, a->mode);
 
        case irms_float_number:
+               if(no_float)
+                       return tarval_bad;
+
                fc_add(a->value, b->value, NULL);
                return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode);
 
@@ -1030,6 +1040,9 @@ tarval *tarval_sub(tarval *a, tarval *b) {
                return get_tarval_overflow(buffer, a->length, a->mode);
 
        case irms_float_number:
+               if(no_float)
+                       return tarval_bad;
+
                fc_sub(a->value, b->value, NULL);
                return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode);
 
@@ -1061,6 +1074,9 @@ tarval *tarval_mul(tarval *a, tarval *b) {
                return get_tarval_overflow(buffer, a->length, a->mode);
 
        case irms_float_number:
+               if(no_float)
+                       return tarval_bad;
+
                fc_mul(a->value, b->value, NULL);
                return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode);
 
@@ -1077,6 +1093,9 @@ tarval *tarval_quo(tarval *a, tarval *b) {
        assert(b);
        assert((a->mode == b->mode) && mode_is_float(a->mode));
 
+       if(no_float)
+               return tarval_bad;
+
        if (get_mode_n_vector_elems(a->mode) > 1) {
                /* vector arithmetic not implemented yet */
                return tarval_bad;
@@ -1152,6 +1171,9 @@ tarval *tarval_abs(tarval *a) {
                return a;
 
        case irms_float_number:
+               if(no_float)
+                       return tarval_bad;
+
                if (fc_comp(a->value, get_mode_null(a->mode)->value) == -1) {
                        fc_neg(a->value, NULL);
                        return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode);