nicer indenting
[libfirm] / ir / be / ia32 / ia32_emitter.c
index a45e9ff..8b5c66b 100644 (file)
@@ -86,8 +86,11 @@ const arch_register_t *get_in_reg(ia32_emit_env_t *env, const ir_node *irn,
 
        assert(reg && "no in register found");
 
-       /* in case of a joker register: just return a valid register */
-       if (arch_register_type_is(reg, joker)) {
+       if(reg == &ia32_gp_regs[REG_GP_NOREG])
+               panic("trying to emit noreg");
+
+       /* in case of unknown register: just return a valid register */
+       if (reg == &ia32_gp_regs[REG_GP_UKNWN]) {
                const arch_register_req_t *req;
 
                /* ask for the requirements */
@@ -155,10 +158,11 @@ char get_mode_suffix(const ir_mode *mode) {
                case 64:
                        return 'l';
                case 80:
+               case 96:
                        return 't';
                }
        } else {
-               assert(mode_is_int(mode) || mode_is_reference(mode) || mode_is_character(mode));
+               assert(mode_is_int(mode) || mode_is_reference(mode));
                switch(get_mode_size_bits(mode)) {
                case 64:
                        return 'q';
@@ -175,12 +179,23 @@ char get_mode_suffix(const ir_mode *mode) {
 
 static
 int produces_result(const ir_node *node) {
-       return !(is_ia32_St(node) ||
-               is_ia32_CondJmp(node) ||
-               is_ia32_xCondJmp(node) ||
-               is_ia32_CmpSet(node) ||
-               is_ia32_xCmpSet(node) ||
-               is_ia32_SwitchJmp(node));
+       return
+               !is_ia32_CmpSet(node)       &&
+               !is_ia32_CmpSet8Bit(node)   &&
+               !is_ia32_CmpJmp(node)       &&
+               !is_ia32_CmpJmp8Bit(node)   &&
+               !is_ia32_St(node)           &&
+               !is_ia32_SwitchJmp(node)    &&
+               !is_ia32_TestJmp(node)      &&
+               !is_ia32_TestJmp8Bit(node)  &&
+               !is_ia32_xCmpSet(node)      &&
+               !is_ia32_xCmpJmp(node)      &&
+               !is_ia32_CmpCMov(node)      &&
+               !is_ia32_CmpCMov8Bit(node)  &&
+               !is_ia32_TestCMov(node)     &&
+               !is_ia32_TestCMov8Bit(node) &&
+               !is_ia32_CmpSet(node)       &&
+               !is_ia32_TestSet(node);
 }
 
 static
@@ -248,41 +263,21 @@ void ia32_emit_dest_register(ia32_emit_env_t *env, const ir_node *node, int pos)
        be_emit_string(env, reg_name);
 }
 
-void ia32_emit_x87_name(ia32_emit_env_t *env, const ir_node *node, int pos)
+static void ia32_emit_register(ia32_emit_env_t *env, const arch_register_t *reg)
 {
-       const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
+       const char *reg_name = arch_register_get_name(reg);
 
-       assert(pos < 3);
        be_emit_char(env, '%');
-       be_emit_string(env, attr->x87[pos]->name);
+       be_emit_string(env, reg_name);
 }
 
-void ia32_emit_immediate(ia32_emit_env_t *env, const ir_node *node)
+void ia32_emit_x87_name(ia32_emit_env_t *env, const ir_node *node, int pos)
 {
-       tarval *tv;
-       ir_entity *ent;
-       ident *id;
-
-       be_emit_char(env, '$');
-
-       switch(get_ia32_immop_type(node)) {
-       case ia32_ImmConst:
-               tv = get_ia32_Immop_tarval(node);
-               be_emit_tarval(env, tv);
-               return;
-       case ia32_ImmSymConst:
-               ent = get_ia32_Immop_symconst(node);
-               mark_entity_visited(ent);
-               id = get_entity_ld_ident(ent);
-               be_emit_ident(env, id);
-               return;
-       case ia32_ImmNone:
-               break;
-       }
+       const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
 
-       assert(0);
-       be_emit_string(env, "BAD");
-       return;
+       assert(pos < 3);
+       be_emit_char(env, '%');
+       be_emit_string(env, attr->x87[pos]->name);
 }
 
 static
@@ -390,24 +385,72 @@ void ia32_emit_function_size(ia32_emit_env_t *env, const char *name)
 static
 void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node);
 
+void ia32_emit_8bit_source_register(ia32_emit_env_t *env, const ir_node *node,
+                                    int pos)
+{
+       const arch_register_t *reg;
+       const char            *reg_name;
+       ir_node               *in;
+
+       in = get_irn_n(node, pos);
+       if(is_ia32_Immediate(in)) {
+               emit_ia32_Immediate(env, in);
+               return;
+       }
+
+       reg      = get_in_reg(env, node, pos);
+       reg_name = arch_register_get_name(reg);
+
+       be_emit_char(env, '%');
+       be_emit_char(env, reg_name[1]);
+       be_emit_char(env, 'l');
+}
+
+void ia32_emit_16bit_source_register(ia32_emit_env_t *env, const ir_node *node,
+                                     int pos)
+{
+       const arch_register_t *reg;
+       const char            *reg_name;
+       ir_node               *in;
+
+       in = get_irn_n(node, pos);
+       if(is_ia32_Immediate(in)) {
+               emit_ia32_Immediate(env, in);
+               return;
+       }
+
+       reg      = get_in_reg(env, node, pos);
+       reg_name = arch_register_get_name(reg);
+
+       be_emit_char(env, '%');
+       be_emit_string(env, &reg_name[1]);
+       be_emit_char(env, 'x');
+}
+
+void ia32_emit_source_register_or_immediate(ia32_emit_env_t *env,
+                                            const ir_node *node, int pos)
+{
+       ir_node *in = get_irn_n(node, pos);
+       if(is_ia32_Immediate(in)) {
+               emit_ia32_Immediate(env, in);
+       } else {
+               ia32_emit_source_register(env, node, pos);
+       }
+}
+
 /**
  * Emits registers and/or address mode of a binary operation.
  */
 void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
-       const ir_node *right_op;
+       const ir_node *right_op = get_irn_n(node, 3);
 
        switch(get_ia32_op_type(node)) {
        case ia32_Normal:
-               right_op = get_irn_n(node, 3);
                if(is_ia32_Immediate(right_op)) {
                        emit_ia32_Immediate(env, right_op);
                        be_emit_cstring(env, ", ");
                        ia32_emit_source_register(env, node, 2);
                        break;
-               } else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
-                       ia32_emit_immediate(env, node);
-                       be_emit_cstring(env, ", ");
-                       ia32_emit_source_register(env, node, 2);
                } else {
                        const arch_register_t *in1 = get_in_reg(env, node, 2);
                        const arch_register_t *in2 = get_in_reg(env, node, 3);
@@ -415,15 +458,10 @@ void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
                        const arch_register_t *in;
                        const char            *in_name;
 
-                       in      = out ? (REGS_ARE_EQUAL(out, in2) ? in1 : in2) : in2;
+                       in      = out ? ((out == in2) ? in1 : in2) : in2;
                        out     = out ? out : in1;
                        in_name = arch_register_get_name(in);
 
-                       if (is_ia32_emit_cl(node)) {
-                               assert(REGS_ARE_EQUAL(&ia32_gp_regs[REG_ECX], in) && "shift operation needs ecx");
-                               in_name = "cl";
-                       }
-
                        be_emit_char(env, '%');
                        be_emit_string(env, in_name);
                        be_emit_cstring(env, ", %");
@@ -431,47 +469,26 @@ void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
                }
                break;
        case ia32_AddrModeS:
-               ia32_emit_am(env, node);
-               be_emit_cstring(env, ", ");
-               if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
-                       assert(!produces_result(node) && "Source AM with Const must not produce result");
-                       ia32_emit_immediate(env, node);
-               } else if (produces_result(node)) {
-                       ia32_emit_dest_register(env, node, 0);
-               } else {
-                       ia32_emit_source_register(env, node, 2);
-               }
-               break;
-       case ia32_AddrModeD:
-               right_op = get_irn_n(node, 3);
                if(is_ia32_Immediate(right_op)) {
+                       assert(!produces_result(node) &&
+                                       "Source AM with Const must not produce result");
+
                        emit_ia32_Immediate(env, right_op);
                        be_emit_cstring(env, ", ");
                        ia32_emit_am(env, node);
-                       break;
-               } else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
-                       ia32_emit_immediate(env, node);
-                       be_emit_cstring(env, ", ");
+               } else if (produces_result(node)) {
                        ia32_emit_am(env, node);
-               } else {
-                       const arch_register_t *in1 = get_in_reg(env, node,
-                                                                   get_irn_arity(node) == 5 ? 3 : 2);
-                       ir_mode               *mode = get_ia32_ls_mode(node);
-                       const char            *in_name;
-
-                       in_name = ia32_get_reg_name_for_mode(env, mode, in1);
-
-                       if (is_ia32_emit_cl(node)) {
-                               assert(REGS_ARE_EQUAL(&ia32_gp_regs[REG_ECX], in1) && "shift operation needs ecx");
-                               in_name = "cl";
-                       }
-
-                       be_emit_char(env, '%');
-                       be_emit_string(env, in_name);
                        be_emit_cstring(env, ", ");
+                       ia32_emit_dest_register(env, node, 0);
+               } else {
                        ia32_emit_am(env, node);
+                       be_emit_cstring(env, ", ");
+                       ia32_emit_source_register(env, node, 2);
                }
                break;
+       case ia32_AddrModeD:
+               panic("DestMode can't be output by %%binop anymore");
+               break;
        default:
                assert(0 && "unsupported op type");
        }
@@ -483,17 +500,14 @@ void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
 void ia32_emit_x87_binop(ia32_emit_env_t *env, const ir_node *node) {
        switch(get_ia32_op_type(node)) {
                case ia32_Normal:
-                       if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
-                               // should not happen...
-                               assert(0);
-                       } else {
+                       {
                                const ia32_x87_attr_t *x87_attr = get_ia32_x87_attr_const(node);
                                const arch_register_t *in1      = x87_attr->x87[0];
                                const arch_register_t *in2      = x87_attr->x87[1];
                                const arch_register_t *out      = x87_attr->x87[2];
                                const arch_register_t *in;
 
-                               in  = out ? (REGS_ARE_EQUAL(out, in2) ? in1 : in2) : in2;
+                               in  = out ? ((out == in2) ? in1 : in2) : in2;
                                out = out ? out : in1;
 
                                be_emit_char(env, '%');
@@ -532,8 +546,6 @@ void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node, int pos) {
                op = get_irn_n(node, pos);
                if (is_ia32_Immediate(op)) {
                        emit_ia32_Immediate(env, op);
-               } else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
-                       ia32_emit_immediate(env, node);
                } else {
                        ia32_emit_source_register(env, node, pos);
                }
@@ -565,7 +577,7 @@ void ia32_emit_am(ia32_emit_env_t *env, const ir_node *node) {
        if (ent != NULL) {
                ident *id;
 
-               mark_entity_visited(ent);
+               set_entity_backend_marked(ent, 1);
                id = get_entity_ld_ident(ent);
                if (is_ia32_am_sc_sign(node))
                        be_emit_char(env, '-');
@@ -609,6 +621,11 @@ void ia32_emit_am(ia32_emit_env_t *env, const ir_node *node) {
                }
                be_emit_char(env, ')');
        }
+
+       /* special case if nothing is set */
+       if(ent == NULL && offs == 0 && !has_base && !has_index) {
+               be_emit_char(env, '0');
+       }
 }
 
 /*************************************************
@@ -645,14 +662,6 @@ const struct cmp2conditon_t cmp2condition_s[] = {
        { "ge",              pn_Cmp_Ge },     /* >= */
        { "ne",              pn_Cmp_Lg },     /* != */
        { NULL,              pn_Cmp_Leg},     /* Floating point: ordered */
-       { NULL,              pn_Cmp_Uo },     /* Floating point: unordered */
-       { "e",               pn_Cmp_Ue },     /* Floating point: unordered or == */
-       { "b",               pn_Cmp_Ul },     /* Floating point: unordered or < */
-       { "be",              pn_Cmp_Ule },    /* Floating point: unordered or <= */
-       { "a",               pn_Cmp_Ug },     /* Floating point: unordered or > */
-       { "ae",              pn_Cmp_Uge },    /* Floating point: unordered or >= */
-       { "ne",              pn_Cmp_Ne },     /* Floating point: unordered or != */
-       { NULL,              pn_Cmp_True },   /* always true */
 };
 
 /*
@@ -676,13 +685,13 @@ const struct cmp2conditon_t cmp2condition_u[] = {
 static
 const char *get_cmp_suffix(pn_Cmp cmp_code)
 {
-       assert( (cmp2condition_s[cmp_code & 15].num) == (cmp_code & 15));
+       assert( (cmp2condition_s[cmp_code & 7].num) == (cmp_code & 7));
        assert( (cmp2condition_u[cmp_code & 7].num) == (cmp_code & 7));
 
        if((cmp_code & ia32_pn_Cmp_Unsigned)) {
                return cmp2condition_u[cmp_code & 7].name;
        } else {
-               return cmp2condition_s[cmp_code & 15].name;
+               return cmp2condition_s[cmp_code & 7].name;
        }
 }
 
@@ -700,15 +709,23 @@ ir_node *get_cfop_target_block(const ir_node *irn) {
        return get_irn_link(irn);
 }
 
+/**
+ * Emits a block label for the given block.
+ */
 static
 void ia32_emit_block_name(ia32_emit_env_t *env, const ir_node *block)
 {
-       be_emit_cstring(env, BLOCK_PREFIX);
-       be_emit_irprintf(env->emit, "%d", get_irn_node_nr(block));
+       if (has_Block_label(block)) {
+               be_emit_string(env, be_gas_label_prefix());
+               be_emit_irprintf(env->emit, "%u", (unsigned)get_Block_label(block));
+       } else {
+               be_emit_cstring(env, BLOCK_PREFIX);
+               be_emit_irprintf(env->emit, "%d", get_irn_node_nr(block));
+       }
 }
 
 /**
- * Returns the target label for a control flow node.
+ * Emits the target label for a control flow node.
  */
 static
 void ia32_emit_cfop_target(ia32_emit_env_t * env, const ir_node *node) {
@@ -780,19 +797,54 @@ void finish_CondJmp(ia32_emit_env_t *env, const ir_node *node, ir_mode *mode,
                pnc        = get_negated_pnc(pnc, mode);
        }
 
-       /* in case of unordered compare, check for parity */
-       if (pnc & pn_Cmp_Uo) {
-               be_emit_cstring(env, "\tjp ");
+       if (mode_is_float(mode)) {
+               /* Some floating point comparisons require a test of the parity flag, which
+                * indicates that the result is unordered */
+               switch (pnc & ~ia32_pn_Cmp_Unsigned) {
+                       case pn_Cmp_Uo:
+                               be_emit_cstring(env, "\tjp ");
+                               ia32_emit_cfop_target(env, proj_true);
+                               be_emit_finish_line_gas(env, proj_true);
+                               break;
+
+                       case pn_Cmp_Leg:
+                               be_emit_cstring(env, "\tjnp ");
+                               ia32_emit_cfop_target(env, proj_true);
+                               be_emit_finish_line_gas(env, proj_true);
+                               break;
+
+                       case pn_Cmp_Eq:
+                       case pn_Cmp_Lt:
+                       case pn_Cmp_Le:
+                               be_emit_cstring(env, "\tjp ");
+                               ia32_emit_cfop_target(env, proj_false);
+                               be_emit_finish_line_gas(env, proj_false);
+                               goto float_jcc;
+
+                       case pn_Cmp_Ug:
+                       case pn_Cmp_Uge:
+                       case pn_Cmp_Ne:
+                               be_emit_cstring(env, "\tjp ");
+                               ia32_emit_cfop_target(env, proj_true);
+                               be_emit_finish_line_gas(env, proj_true);
+                               goto float_jcc;
+
+                       default:
+                       float_jcc:
+                               /* The bits set by floating point compares correspond to unsigned
+                                * comparisons */
+                               pnc |= ia32_pn_Cmp_Unsigned;
+                               goto emit_jcc;
+               }
+       } else {
+emit_jcc:
+               be_emit_cstring(env, "\tj");
+               ia32_emit_cmp_suffix(env, pnc);
+               be_emit_char(env, ' ');
                ia32_emit_cfop_target(env, proj_true);
                be_emit_finish_line_gas(env, proj_true);
        }
 
-       be_emit_cstring(env, "\tj");
-       ia32_emit_cmp_suffix(env, pnc);
-       be_emit_char(env, ' ');
-       ia32_emit_cfop_target(env, proj_true);
-       be_emit_finish_line_gas(env, proj_true);
-
        /* the second Proj might be a fallthrough */
        if (get_cfop_target_block(proj_false) != next_block) {
                be_emit_cstring(env, "\tjmp ");
@@ -811,7 +863,9 @@ void finish_CondJmp(ia32_emit_env_t *env, const ir_node *node, ir_mode *mode,
  */
 static
 void CondJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
-       be_emit_cstring(env, "\tcmp ");
+       be_emit_cstring(env, "\tcmp");
+       ia32_emit_mode_suffix(env, node);
+       be_emit_char(env, ' ');
        ia32_emit_binop(env, node);
        be_emit_finish_line_gas(env, node);
 
@@ -822,7 +876,7 @@ void CondJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
  * Emits code for conditional jump with two variables.
  */
 static
-void emit_ia32_CondJmp(ia32_emit_env_t *env, const ir_node *node) {
+void emit_ia32_CmpJmp(ia32_emit_env_t *env, const ir_node *node) {
        CondJmp_emitter(env, node);
 }
 
@@ -831,19 +885,13 @@ void emit_ia32_CondJmp(ia32_emit_env_t *env, const ir_node *node) {
  */
 static
 void TestJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
-       if(is_ia32_ImmSymConst(node) || is_ia32_ImmConst(node)) {
-               be_emit_cstring(env, "\ttest ");
-               ia32_emit_immediate(env, node);
-               be_emit_cstring(env, ", ");
-               ia32_emit_source_register(env, node, 0);
-               be_emit_finish_line_gas(env, node);
-       } else {
-               be_emit_cstring(env, "\ttest ");
-               ia32_emit_source_register(env, node, 1);
-               be_emit_cstring(env, ", ");
-               ia32_emit_source_register(env, node, 0);
-               be_emit_finish_line_gas(env, node);
-       }
+       be_emit_cstring(env, "\ttest");
+       ia32_emit_mode_suffix(env, node);
+       be_emit_char(env, ' ');
+
+       ia32_emit_binop(env, node);
+       be_emit_finish_line_gas(env, node);
+
        finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
 }
 
@@ -855,27 +903,11 @@ void emit_ia32_TestJmp(ia32_emit_env_t *env, const ir_node *node) {
        TestJmp_emitter(env, node);
 }
 
-static
-void emit_ia32_CJmp(ia32_emit_env_t *env, const ir_node *node) {
-       be_emit_cstring(env, "/* omitted redundant test */");
-       be_emit_finish_line_gas(env, node);
-
-       finish_CondJmp(env, node, mode_Is, get_ia32_pncode(node));
-}
-
-static
-void emit_ia32_CJmpAM(ia32_emit_env_t *env, const ir_node *node) {
-       be_emit_cstring(env, "/* omitted redundant test/cmp */");
-       be_emit_finish_line_gas(env, node);
-
-       finish_CondJmp(env, node, mode_Is, get_ia32_pncode(node));
-}
-
 /**
  * Emits code for conditional SSE floating point jump with two variables.
  */
 static
-void emit_ia32_xCondJmp(ia32_emit_env_t *env, const ir_node *node) {
+void emit_ia32_xCmpJmp(ia32_emit_env_t *env, const ir_node *node) {
        be_emit_cstring(env, "\tucomi");
        ia32_emit_xmm_mode_suffix(env, node);
        be_emit_char(env, ' ');
@@ -889,7 +921,7 @@ void emit_ia32_xCondJmp(ia32_emit_env_t *env, const ir_node *node) {
  * Emits code for conditional x87 floating point jump with two variables.
  */
 static
-void emit_ia32_x87CondJmp(ia32_emit_env_t *env, const ir_node *node) {
+void emit_ia32_x87CmpJmp(ia32_emit_env_t *env, const ir_node *node) {
        const ia32_x87_attr_t *x87_attr = get_ia32_x87_attr_const(node);
        const char            *reg      = x87_attr->x87[1]->name;
        long                   pnc      = get_ia32_pncode(node);
@@ -930,96 +962,68 @@ void emit_ia32_x87CondJmp(ia32_emit_env_t *env, const ir_node *node) {
        finish_CondJmp(env, node, mode_E, pnc);
 }
 
-static
-void emit_register_or_immediate(ia32_emit_env_t *env, const ir_node *node,
-                                int pos)
-{
-       ir_node *op = get_irn_n(node, pos);
-       if(is_ia32_Immediate(op)) {
-               emit_ia32_Immediate(env, op);
-       } else {
-               ia32_emit_source_register(env, node, pos);
-       }
-}
-
-static
-int is_ia32_Immediate_0(const ir_node *node)
-{
-       const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node);
-       tarval                      *tv   = attr->offset;
-
-       if(tv == NULL || attr->symconst != NULL)
-               return 0;
-
-       return classify_tarval(tv) == CNST_NULL;
-}
-
 static
 void CMov_emitter(ia32_emit_env_t *env, const ir_node *node)
 {
-       long pnc = get_ia32_pncode(node);
        const arch_register_t *in1, *in2, *out;
+       long  pnc = get_ia32_pncode(node);
 
        out = arch_get_irn_register(env->arch_env, node);
-       in1 = arch_get_irn_register(env->arch_env, get_irn_n(node, 2));
-       in2 = arch_get_irn_register(env->arch_env, get_irn_n(node, 3));
 
        /* we have to emit the cmp first, because the destination register */
        /* could be one of the compare registers                           */
-       if (is_ia32_CmpCMov(node)) {
-               long pncr = pnc & ~ia32_pn_Cmp_Unsigned;
-               ir_node *cmp_right = get_irn_n(node, 1);
-
-               if( (pncr == pn_Cmp_Eq || pncr == pn_Cmp_Lg)
-                               && is_ia32_Immediate(cmp_right)
-                               && is_ia32_Immediate_0(cmp_right)) {
-                       be_emit_cstring(env, "\ttest ");
-                       ia32_emit_source_register(env, node, 0);
-                       be_emit_cstring(env, ", ");
-                       ia32_emit_source_register(env, node, 0);
-               } else {
-                       be_emit_cstring(env, "\tcmp ");
-                       emit_register_or_immediate(env, node, 1);
-                       be_emit_cstring(env, ", ");
-                       ia32_emit_source_register(env, node, 0);
-               }
-       } else if (is_ia32_xCmpCMov(node)) {
+       if (is_ia32_xCmpCMov(node)) {
                be_emit_cstring(env, "\tucomis");
                ia32_emit_mode_suffix_mode(env, get_irn_mode(node));
                be_emit_char(env, ' ');
                ia32_emit_source_register(env, node, 1);
                be_emit_cstring(env, ", ");
                ia32_emit_source_register(env, node, 0);
+
+               in1 = arch_get_irn_register(env->arch_env, get_irn_n(node, 2));
+               in2 = arch_get_irn_register(env->arch_env, get_irn_n(node, 3));
        } else {
-               assert(0 && "unsupported CMov");
+               if (is_ia32_CmpCMov(node) || is_ia32_CmpCMov8Bit(node)) {
+                       be_emit_cstring(env, "\tcmp ");
+               } else {
+                       assert(is_ia32_TestCMov(node) || is_ia32_TestCMov8Bit(node));
+                       be_emit_cstring(env, "\ttest ");
+               }
+               ia32_emit_binop(env, node);
+
+               in1 = arch_get_irn_register(env->arch_env, get_irn_n(node, 5));
+               in2 = arch_get_irn_register(env->arch_env, get_irn_n(node, 6));
        }
        be_emit_finish_line_gas(env, node);
 
-       if (REGS_ARE_EQUAL(out, in2)) {
+       if (out == in2) {
                /* best case: default in == out -> do nothing */
-       } else if (REGS_ARE_EQUAL(out, in1)) {
-               ir_node *n = (ir_node*) node;
-               /* true in == out -> need complement compare and exchange true and default in */
-               ir_node *t = get_irn_n(n, 2);
-               set_irn_n(n, 2, get_irn_n(n, 3));
-               set_irn_n(n, 3, t);
-
+       } else if(in2 == &ia32_gp_regs[REG_GP_UKNWN]) {
+               /* also nothign to do for unknown regs */
+       } else if (out == in1) {
+               const arch_register_t *t;
+               /* true in == out -> need complement compare and exchange true and
+                * default in */
+               t   = in1;
+               in1 = in2;
+               in2 = t;
                pnc = get_negated_pnc(pnc, get_irn_mode(node));
        } else {
-               /* out is different from in: need copy default -> out */
+               /* out is different from both ins: need copy default -> out */
                be_emit_cstring(env, "\tmovl ");
-               ia32_emit_source_register(env, node, n_ia32_CmpCMov_val_false);
+               ia32_emit_register(env, in2);
                be_emit_cstring(env, ", ");
-               ia32_emit_dest_register(env, node, 0);
+               ia32_emit_register(env, out);
                be_emit_finish_line_gas(env, node);
        }
 
        be_emit_cstring(env, "\tcmov");
-       ia32_emit_cmp_suffix(env, pnc);
+       ia32_emit_cmp_suffix(env, pnc );
        be_emit_cstring(env, "l ");
-       ia32_emit_source_register(env, node, n_ia32_CmpCMov_val_true);
+       ia32_emit_register(env, in1);
        be_emit_cstring(env, ", ");
-       ia32_emit_dest_register(env, node, 0);
+       ia32_emit_register(env, out);
+
        be_emit_finish_line_gas(env, node);
 }
 
@@ -1029,6 +1033,12 @@ void emit_ia32_CmpCMov(ia32_emit_env_t *env, const ir_node *node)
        CMov_emitter(env, node);
 }
 
+static
+void emit_ia32_TestCMov(ia32_emit_env_t *env, const ir_node *node)
+{
+       CMov_emitter(env, node);
+}
+
 static
 void emit_ia32_xCmpCMov(ia32_emit_env_t *env, const ir_node *node)
 {
@@ -1045,36 +1055,24 @@ void Set_emitter(ia32_emit_env_t *env, const ir_node *node)
        out     = arch_get_irn_register(env->arch_env, node);
        reg8bit = ia32_get_mapped_reg_name(env->isa->regs_8bit, out);
 
-       if (is_ia32_CmpSet(node)) {
-               long     pncr      = pnc & ~ia32_pn_Cmp_Unsigned;
-               ir_node *cmp_right = get_irn_n(node, n_ia32_CmpSet_cmp_right);
-
-               if( (pncr == pn_Cmp_Eq || pncr == pn_Cmp_Lg)
-                               && is_ia32_Immediate(cmp_right)
-                               && is_ia32_Immediate_0(cmp_right)) {
-                       be_emit_cstring(env, "\ttest ");
-                       ia32_emit_source_register(env, node, n_ia32_CmpSet_cmp_left);
-                       be_emit_cstring(env, ", ");
-                       ia32_emit_source_register(env, node, n_ia32_CmpSet_cmp_left);
-               } else {
-                       be_emit_cstring(env, "\tcmp ");
-                       ia32_emit_binop(env, node);
-               }
-       } else if (is_ia32_xCmpSet(node)) {
+       if(is_ia32_xCmpSet(node)) {
                be_emit_cstring(env, "\tucomis");
                ia32_emit_mode_suffix_mode(env, get_irn_mode(get_irn_n(node, 2)));
                be_emit_char(env, ' ');
                ia32_emit_binop(env, node);
        } else {
-               assert(0 && "unsupported Set");
+               if (is_ia32_CmpSet(node) || is_ia32_CmpSet8Bit(node)) {
+                       be_emit_cstring(env, "\tcmp");
+               } else {
+                       assert(is_ia32_TestSet(node) || is_ia32_TestSet8Bit(node));
+                       be_emit_cstring(env, "\ttest");
+               }
+               ia32_emit_mode_suffix(env, node);
+               be_emit_char(env, ' ');
+               ia32_emit_binop(env, node);
        }
        be_emit_finish_line_gas(env, node);
 
-       /* use mov to clear target because it doesn't affect the eflags */
-       be_emit_cstring(env, "\tmovl $0, %");
-       be_emit_string(env, arch_register_get_name(out));
-       be_emit_finish_line_gas(env, node);
-
        be_emit_cstring(env, "\tset");
        ia32_emit_cmp_suffix(env, pnc);
        be_emit_cstring(env, " %");
@@ -1087,6 +1085,11 @@ void emit_ia32_CmpSet(ia32_emit_env_t *env, const ir_node *node) {
        Set_emitter(env, node);
 }
 
+static
+void emit_ia32_TestSet(ia32_emit_env_t *env, const ir_node *node) {
+       Set_emitter(env, node);
+}
+
 static
 void emit_ia32_xCmpSet(ia32_emit_env_t *env, const ir_node *node) {
        Set_emitter(env, node);
@@ -1352,7 +1355,7 @@ void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node)
 {
        const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node);
 
-       assert(attr->symconst != NULL || attr->offset != NULL);
+       be_emit_char(env, '$');
        if(attr->symconst != NULL) {
                ident *id = get_entity_ld_ident(attr->symconst);
 
@@ -1360,12 +1363,10 @@ void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node)
                        be_emit_char(env, '-');
                be_emit_ident(env, id);
        }
-       if(attr->offset != NULL) {
+       if(attr->symconst == NULL || attr->offset != 0) {
                if(attr->symconst != NULL)
                        be_emit_char(env, '+');
-               else
-                       be_emit_char(env, '$');
-               be_emit_tarval(env, attr->offset);
+               be_emit_irprintf(env->emit, "0x%X", attr->offset);
        }
 }
 
@@ -1555,8 +1556,7 @@ void emit_CopyB_prolog(ia32_emit_env_t *env, int rem) {
  */
 static
 void emit_ia32_CopyB(ia32_emit_env_t *env, const ir_node *node) {
-       tarval *tv = get_ia32_Immop_tarval(node);
-       int    rem = get_tarval_long(tv);
+       int rem = get_ia32_pncode(node);
 
        emit_CopyB_prolog(env, rem);
 
@@ -1569,8 +1569,7 @@ void emit_ia32_CopyB(ia32_emit_env_t *env, const ir_node *node) {
  */
 static
 void emit_ia32_CopyB_i(ia32_emit_env_t *env, const ir_node *node) {
-       tarval *tv   = get_ia32_Immop_tarval(node);
-       int     size = get_tarval_long(tv);
+       int size = get_ia32_pncode(node);
 
        emit_CopyB_prolog(env, size & 0x3);
 
@@ -1685,8 +1684,8 @@ void emit_ia32_Conv_I2I(ia32_emit_env_t *env, const ir_node *node) {
                        in_reg  = get_in_reg(env, node, 2);
                        out_reg = get_out_reg(env, node, 0);
 
-                       if (REGS_ARE_EQUAL(in_reg, &ia32_gp_regs[REG_EAX]) &&
-                               REGS_ARE_EQUAL(out_reg, in_reg)                &&
+                       if (in_reg  == &ia32_gp_regs[REG_EAX] &&
+                               out_reg == &ia32_gp_regs[REG_EAX] &&
                                signed_mode &&
                                smaller_bits == 16)
                        {
@@ -1709,7 +1708,7 @@ void emit_ia32_Conv_I2I(ia32_emit_env_t *env, const ir_node *node) {
                        be_emit_cstring(env, "\tmov");
                        be_emit_string(env, sign_suffix);
                        ia32_emit_mode_suffix_mode(env, smaller_mode);
-                       be_emit_cstring(env, "l %");
+                       be_emit_cstring(env, "l ");
                        ia32_emit_am(env, node);
                        be_emit_cstring(env, ", ");
                        ia32_emit_dest_register(env, node, 0);
@@ -1748,7 +1747,7 @@ void emit_be_Call(ia32_emit_env_t *env, const ir_node *node) {
 
        be_emit_cstring(env, "\tcall ");
        if (ent) {
-               mark_entity_visited(ent);
+               set_entity_backend_marked(ent, 1);
                be_emit_string(env, get_entity_ld_name(ent));
        } else {
                be_emit_char(env, '*');
@@ -1797,24 +1796,31 @@ void emit_be_SetSP(ia32_emit_env_t *env, const ir_node *node) {
 static
 void Copy_emitter(ia32_emit_env_t *env, const ir_node *node, const ir_node *op)
 {
-       const arch_env_t *aenv = env->arch_env;
+       const arch_env_t      *arch_env = env->arch_env;
+       const arch_register_t *in       = arch_get_irn_register(arch_env, op);
+       const arch_register_t *out      = arch_get_irn_register(arch_env, node);
        ir_mode *mode;
 
-       if (REGS_ARE_EQUAL(arch_get_irn_register(aenv, node), arch_get_irn_register(aenv, op)) ||
-               arch_register_type_is(arch_get_irn_register(aenv, op), virtual))
+       if(in == out) {
+               return;
+       }
+       if(is_unknown_reg(in))
+               return;
+       /* copies of vf nodes aren't real... */
+       if(arch_register_get_class(in) == &ia32_reg_classes[CLASS_ia32_vfp])
                return;
 
        mode = get_irn_mode(node);
        if (mode == mode_E) {
                be_emit_cstring(env, "\tmovsd ");
-               ia32_emit_source_register(env, node, 0);
+               ia32_emit_register(env, in);
                be_emit_cstring(env, ", ");
-               ia32_emit_dest_register(env, node, 0);
+               ia32_emit_register(env, out);
        } else {
                be_emit_cstring(env, "\tmovl ");
-               ia32_emit_source_register(env, node, 0);
+               ia32_emit_register(env, in);
                be_emit_cstring(env, ", ");
-               ia32_emit_dest_register(env, node, 0);
+               ia32_emit_register(env, out);
        }
        be_emit_finish_line_gas(env, node);
 }
@@ -1881,34 +1887,26 @@ void emit_be_Perm(ia32_emit_env_t *env, const ir_node *node) {
  */
 static
 void emit_ia32_Const(ia32_emit_env_t *env, const ir_node *node) {
-       ia32_immop_type_t imm_tp = get_ia32_immop_type(node);
+       const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node);
 
-       if (imm_tp == ia32_ImmSymConst) {
-               be_emit_cstring(env, "\tmovl ");
-               ia32_emit_immediate(env, node);
+       /* a zero? */
+       if(attr->symconst == NULL && attr->offset == 0) {
+               if (env->isa->opt_arch == arch_pentium_4) {
+                       /* P4 prefers sub r, r, others xor r, r */
+                       be_emit_cstring(env, "\tsubl ");
+               } else {
+                       be_emit_cstring(env, "\txorl ");
+               }
+               ia32_emit_dest_register(env, node, 0);
                be_emit_cstring(env, ", ");
                ia32_emit_dest_register(env, node, 0);
        } else {
-               tarval *tv = get_ia32_Immop_tarval(node);
-               assert(get_irn_mode(node) == mode_Iu);
-               /* beware: in some rare cases mode is mode_b which has no tarval_null() */
-               if (tarval_is_null(tv)) {
-                       if (env->isa->opt_arch == arch_pentium_4) {
-                               /* P4 prefers sub r, r, others xor r, r */
-                               be_emit_cstring(env, "\tsubl ");
-                       } else {
-                               be_emit_cstring(env, "\txorl ");
-                       }
-                       ia32_emit_dest_register(env, node, 0);
-                       be_emit_cstring(env, ", ");
-                       ia32_emit_dest_register(env, node, 0);
-               } else {
-                       be_emit_cstring(env, "\tmovl ");
-                       ia32_emit_immediate(env, node);
-                       be_emit_cstring(env, ", ");
-                       ia32_emit_dest_register(env, node, 0);
-               }
+               be_emit_cstring(env, "\tmovl ");
+               emit_ia32_Immediate(env, node);
+               be_emit_cstring(env, ", ");
+               ia32_emit_dest_register(env, node, 0);
        }
+
        be_emit_finish_line_gas(env, node);
 }
 
@@ -1969,12 +1967,18 @@ void ia32_register_emitters(void) {
 
        /* other ia32 emitter functions */
        IA32_EMIT(Asm);
-       IA32_EMIT(CondJmp);
+       IA32_EMIT(CmpJmp);
+       IA32_EMIT2(CmpJmp8Bit, CmpJmp);
        IA32_EMIT(TestJmp);
-       IA32_EMIT(CJmp);
-       IA32_EMIT(CJmpAM);
+       IA32_EMIT2(TestJmp8Bit, TestJmp);
        IA32_EMIT(CmpCMov);
+       IA32_EMIT2(CmpCMov8Bit, CmpCMov);
+       IA32_EMIT(TestCMov);
+       IA32_EMIT2(TestCMov8Bit, TestCMov);
        IA32_EMIT(CmpSet);
+       IA32_EMIT2(CmpSet8Bit, CmpSet);
+       IA32_EMIT(TestSet);
+       IA32_EMIT2(TestSet8Bit, TestSet);
        IA32_EMIT(SwitchJmp);
        IA32_EMIT(CopyB);
        IA32_EMIT(CopyB_i);
@@ -1988,13 +1992,13 @@ void ia32_register_emitters(void) {
        IA32_EMIT(xCmp);
        IA32_EMIT(xCmpSet);
        IA32_EMIT(xCmpCMov);
-       IA32_EMIT(xCondJmp);
-       IA32_EMIT2(fcomJmp, x87CondJmp);
-       IA32_EMIT2(fcompJmp, x87CondJmp);
-       IA32_EMIT2(fcomppJmp, x87CondJmp);
-       IA32_EMIT2(fcomrJmp, x87CondJmp);
-       IA32_EMIT2(fcomrpJmp, x87CondJmp);
-       IA32_EMIT2(fcomrppJmp, x87CondJmp);
+       IA32_EMIT(xCmpJmp);
+       IA32_EMIT2(fcomJmp, x87CmpJmp);
+       IA32_EMIT2(fcompJmp, x87CmpJmp);
+       IA32_EMIT2(fcomppJmp, x87CmpJmp);
+       IA32_EMIT2(fcomrJmp, x87CmpJmp);
+       IA32_EMIT2(fcomrpJmp, x87CmpJmp);
+       IA32_EMIT2(fcomrppJmp, x87CmpJmp);
 
        /* benode emitter */
        BE_EMIT(Call);
@@ -2074,7 +2078,8 @@ void ia32_emit_node(ia32_emit_env_t *env, const ir_node *node) {
                (*func) (env, node);
        } else {
                emit_Nothing(env, node);
-               ir_fprintf(stderr, "Warning: No emit handler for node %+F (%+G)\n", node, node);
+               ir_fprintf(stderr, "Error: No emit handler for node %+F (%+G, graph %+F)\n", node, node, current_ir_graph);
+               abort();
        }
 }
 
@@ -2197,25 +2202,8 @@ void ia32_emit_block_header(ia32_emit_env_t *env, ir_node *block, ir_node *prev)
        int           i, arity;
        ir_exec_freq  *exec_freq = env->cg->birg->exec_freq;
 
-       need_label = 1;
        n_cfgpreds = get_Block_n_cfgpreds(block);
-       if (n_cfgpreds == 0) {
-               need_label = 0;
-       } else if (n_cfgpreds == 1) {
-               ir_node *pred       = get_Block_cfgpred(block, 0);
-               ir_node *pred_block = get_nodes_block(pred);
-
-               /* we don't need labels for fallthrough blocks, however switch-jmps
-                * are no fallthoughs */
-               if(pred_block == prev &&
-                               !(is_Proj(pred) && is_ia32_SwitchJmp(get_Proj_pred(pred)))) {
-                       need_label = 0;
-               } else {
-                       need_label = 1;
-               }
-       } else {
-               need_label = 1;
-       }
+       need_label = (n_cfgpreds != 0);
 
        if (should_align_block(env, block, prev)) {
                assert(need_label);