reworked ia32 condition code handling, remove backend Bound support (really someone...
authorMatthias Braun <matze@braunis.de>
Thu, 17 Feb 2011 00:13:53 +0000 (00:13 +0000)
committerMatthias Braun <matze@braunis.de>
Thu, 17 Feb 2011 00:13:53 +0000 (00:13 +0000)
[r28386]

ir/be/ia32/ia32_emitter.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

index 4667d3a..009d071 100644 (file)
  * @version     $Id$
  *
  * Summary table for x86 floatingpoint compares:
+ * (remember effect of unordered on x86: ZF=1, PF=1, CF=1)
+ *
  *   pnc_Eq  => !P && E
  *   pnc_Lt  => !P && B
  *   pnc_Le  => !P && BE
  *   pnc_Gt  => A
  *   pnc_Ge  => AE
- *   pnc_Lg  => P || NE
+ *   pnc_Lg  => NE
  *   pnc_Leg => NP  (ordered)
  *   pnc_Uo  => P
  *   pnc_Ue  => E
@@ -37,7 +39,7 @@
  *   pnc_Ule => BE
  *   pnc_Ug  => P || A
  *   pnc_Uge => P || AE
- *   pnc_Ne  => NE
+ *   pnc_Ne  => P || NE
  */
 #include "config.h"
 
@@ -497,53 +499,43 @@ static void ia32_emit_cfop_target(const ir_node *node)
        be_gas_emit_block_name(block);
 }
 
-/*
- * positive conditions for signed compares
- */
-static const char *const cmp2condition_s[] = {
-       NULL, /* always false */
-       "e",  /* == */
-       "l",  /* <  */
-       "le", /* <= */
-       "g",  /* >  */
-       "ge", /* >= */
-       "ne", /* != */
-       NULL  /* always true */
-};
-
-/*
- * positive conditions for unsigned compares
- */
-static const char *const cmp2condition_u[] = {
-       NULL, /* always false */
-       "e",  /* == */
-       "b",  /* <  */
-       "be", /* <= */
-       "a",  /* >  */
-       "ae", /* >= */
-       "ne", /* != */
-       NULL  /* always true */
-};
-
 /**
  * Emit the suffix for a compare instruction.
  */
-static void ia32_emit_cmp_suffix(int pnc)
-{
-       const char *str;
-
-       if (pnc == ia32_pn_Cmp_parity) {
-               be_emit_char('p');
-               return;
-       }
-
-       if (pnc & ia32_pn_Cmp_float || pnc & ia32_pn_Cmp_unsigned) {
-               str = cmp2condition_u[pnc & 7];
-       } else {
-               str = cmp2condition_s[pnc & 7];
+static void ia32_emit_condition_code(ia32_condition_code_t cc)
+{
+       switch (cc) {
+       case ia32_cc_overflow:      be_emit_cstring("o");  return;
+       case ia32_cc_not_overflow:  be_emit_cstring("no"); return;
+       case ia32_cc_float_below:
+       case ia32_cc_float_unordered_below:
+       case ia32_cc_below:         be_emit_cstring("b");  return;
+       case ia32_cc_float_above_equal:
+       case ia32_cc_float_unordered_above_equal:
+       case ia32_cc_above_equal:   be_emit_cstring("ae"); return;
+       case ia32_cc_float_equal:
+       case ia32_cc_equal:         be_emit_cstring("e");  return;
+       case ia32_cc_float_not_equal:
+       case ia32_cc_not_equal:     be_emit_cstring("ne"); return;
+       case ia32_cc_float_below_equal:
+       case ia32_cc_float_unordered_below_equal:
+       case ia32_cc_below_equal:   be_emit_cstring("be"); return;
+       case ia32_cc_float_above:
+       case ia32_cc_float_unordered_above:
+       case ia32_cc_above:         be_emit_cstring("a");  return;
+       case ia32_cc_sign:          be_emit_cstring("s");  return;
+       case ia32_cc_not_sign:      be_emit_cstring("ns"); return;
+       case ia32_cc_parity:        be_emit_cstring("p");  return;
+       case ia32_cc_not_parity:    be_emit_cstring("np"); return;
+       case ia32_cc_less:          be_emit_cstring("l");  return;
+       case ia32_cc_greater_equal: be_emit_cstring("ge"); return;
+       case ia32_cc_less_equal:    be_emit_cstring("le"); return;
+       case ia32_cc_greater:       be_emit_cstring("g");  return;
+       case ia32_cc_float_parity_cases:
+       case ia32_cc_additional_float_cases:
+               break;
        }
-
-       be_emit_string(str);
+       panic("Invalid ia32 condition code");
 }
 
 typedef enum ia32_emit_mod_t {
@@ -749,8 +741,8 @@ emit_AM:
                        }
 
                        case 'P': {
-                               int pnc = va_arg(ap, int);
-                               ia32_emit_cmp_suffix(pnc);
+                               ia32_condition_code_t cc = va_arg(ap, ia32_condition_code_t);
+                               ia32_emit_condition_code(cc);
                                break;
                        }
 
@@ -939,7 +931,7 @@ static ir_node *find_original_value(ir_node *node)
        }
 }
 
-static int determine_final_pnc(const ir_node *node, int flags_pos, int pnc)
+static int determine_final_cc(const ir_node *node, int flags_pos, int cc)
 {
        ir_node           *flags = get_irn_n(node, flags_pos);
        const ia32_attr_t *flags_attr;
@@ -957,40 +949,21 @@ static int determine_final_pnc(const ir_node *node, int flags_pos, int pnc)
                }
 
                flags_attr = get_ia32_attr_const(cmp);
-               if (flags_attr->data.ins_permuted)
-                       pnc = get_mirrored_pnc(pnc);
-               pnc |= ia32_pn_Cmp_float;
-       } else if (is_ia32_Ucomi(flags) || is_ia32_Fucomi(flags)
-                       || is_ia32_Fucompi(flags)) {
-               flags_attr = get_ia32_attr_const(flags);
-
-               if (flags_attr->data.ins_permuted)
-                       pnc = get_mirrored_pnc(pnc);
-               pnc |= ia32_pn_Cmp_float;
        } else {
                flags_attr = get_ia32_attr_const(flags);
-
-               if (flags_attr->data.ins_permuted)
-                       pnc = get_mirrored_pnc(pnc);
-               if (flags_attr->data.cmp_unsigned)
-                       pnc |= ia32_pn_Cmp_unsigned;
        }
 
-       return pnc;
-}
-
-static int ia32_get_negated_pnc(int pnc)
-{
-       ir_mode *mode = pnc & ia32_pn_Cmp_float ? mode_F : mode_Iu;
-       return get_negated_pnc(pnc, mode);
+       if (flags_attr->data.ins_permuted)
+               cc = ia32_invert_condition_code(cc);
+       return cc;
 }
 
 void ia32_emit_cmp_suffix_node(const ir_node *node, int flags_pos)
 {
-       int pnc = get_ia32_condcode(node);
-       pnc = determine_final_pnc(node, flags_pos, pnc);
+       ia32_condition_code_t cc = get_ia32_condcode(node);
+       cc = determine_final_cc(node, flags_pos, cc);
 
-       ia32_emit_cmp_suffix(pnc);
+       ia32_emit_condition_code(cc);
 }
 
 /**
@@ -1037,12 +1010,12 @@ static int can_be_fallthrough(const ir_node *node)
  */
 static void emit_ia32_Jcc(const ir_node *node)
 {
-       int            need_parity_label = 0;
-       const ir_node *proj_true;
-       const ir_node *proj_false;
-       int            pnc = get_ia32_condcode(node);
+       int                   need_parity_label = 0;
+       ia32_condition_code_t cc                = get_ia32_condcode(node);
+       const ir_node        *proj_true;
+       const ir_node        *proj_false;
 
-       pnc = determine_final_pnc(node, 0, pnc);
+       cc = determine_final_cc(node, 0, cc);
 
        /* get both Projs */
        proj_true = get_proj(node, pn_ia32_Jcc_true);
@@ -1057,25 +1030,15 @@ static void emit_ia32_Jcc(const ir_node *node)
 
                proj_true  = proj_false;
                proj_false = t;
-               pnc        = ia32_get_negated_pnc(pnc);
+               cc         = ia32_negate_condition_code(cc);
        }
 
-       if (pnc & ia32_pn_Cmp_float) {
+       if (cc & ia32_cc_float_parity_cases) {
                /* Some floating point comparisons require a test of the parity flag,
                 * which indicates that the result is unordered */
-               switch (pnc & 0x0f) {
-               case pn_Cmp_Uo: {
+               if (cc & ia32_cc_negated) {
                        ia32_emitf(proj_true, "\tjp %L\n");
-                       break;
-               }
-
-               case pn_Cmp_Leg:
-                       ia32_emitf(proj_true, "\tjnp %L\n");
-                       break;
-
-               case pn_Cmp_Eq:
-               case pn_Cmp_Lt:
-               case pn_Cmp_Le:
+               } else {
                        /* we need a local label if the false proj is a fallthrough
                         * as the falseblock might have no label emitted then */
                        if (can_be_fallthrough(proj_false)) {
@@ -1084,22 +1047,9 @@ static void emit_ia32_Jcc(const ir_node *node)
                        } else {
                                ia32_emitf(proj_false, "\tjp %L\n");
                        }
-                       goto emit_jcc;
-
-               case pn_Cmp_Ug:
-               case pn_Cmp_Uge:
-               case pn_Cmp_Ne:
-                       ia32_emitf(proj_true, "\tjp %L\n");
-                       goto emit_jcc;
-
-               default:
-                       goto emit_jcc;
                }
-       } else {
-emit_jcc:
-               ia32_emitf(proj_true, "\tj%P %L\n", pnc);
        }
-
+       ia32_emitf(proj_true, "\tj%P %L\n", cc);
        if (need_parity_label) {
                ia32_emitf(NULL, "1:\n");
        }
@@ -1120,56 +1070,38 @@ static void emit_ia32_Setcc(const ir_node *node)
 {
        const arch_register_t *dreg = get_out_reg(node, pn_ia32_Setcc_res);
 
-       int pnc = get_ia32_condcode(node);
-       pnc     = determine_final_pnc(node, n_ia32_Setcc_eflags, pnc);
-       if (pnc & ia32_pn_Cmp_float) {
-               switch (pnc & 0x0f) {
-               case pn_Cmp_Uo:
-                       ia32_emitf(node, "\tsetp %#R\n", dreg);
-                       return;
-
-               case pn_Cmp_Leg:
-                       ia32_emitf(node, "\tsetnp %#R\n", dreg);
-                       return;
-
-               case pn_Cmp_Eq:
-               case pn_Cmp_Lt:
-               case pn_Cmp_Le:
-                       ia32_emitf(node, "\tset%P %<R\n", pnc, dreg);
-                       ia32_emitf(node, "\tsetnp %>R\n", dreg);
-                       ia32_emitf(node, "\tandb %>R, %<R\n", dreg, dreg);
-                       return;
-
-               case pn_Cmp_Ug:
-               case pn_Cmp_Uge:
-               case pn_Cmp_Ne:
-                       ia32_emitf(node, "\tset%P %<R\n", pnc, dreg);
+       ia32_condition_code_t cc = get_ia32_condcode(node);
+       cc = determine_final_cc(node, n_ia32_Setcc_eflags, cc);
+       if (cc & ia32_cc_float_parity_cases) {
+               if (cc & ia32_cc_negated) {
+                       ia32_emitf(node, "\tset%P %<R\n", cc, dreg);
                        ia32_emitf(node, "\tsetp %>R\n", dreg);
                        ia32_emitf(node, "\torb %>R, %<R\n", dreg, dreg);
-                       return;
-
-               default:
-                       break;
+               } else {
+                       ia32_emitf(node, "\tset%P %<R\n", cc, dreg);
+                       ia32_emitf(node, "\tsetnp %>R\n", dreg);
+                       ia32_emitf(node, "\tandb %>R, %<R\n", dreg, dreg);
                }
+       } else {
+               ia32_emitf(node, "\tset%P %#R\n", cc, dreg);
        }
-       ia32_emitf(node, "\tset%P %#R\n", pnc, dreg);
 }
 
 static void emit_ia32_CMovcc(const ir_node *node)
 {
        const ia32_attr_t     *attr = get_ia32_attr_const(node);
        const arch_register_t *out  = arch_irn_get_register(node, pn_ia32_res);
-       int                    pnc  = get_ia32_condcode(node);
+       ia32_condition_code_t  cc   = get_ia32_condcode(node);
        const arch_register_t *in_true;
        const arch_register_t *in_false;
 
-       pnc = determine_final_pnc(node, n_ia32_CMovcc_eflags, pnc);
+       cc = determine_final_cc(node, n_ia32_CMovcc_eflags, cc);
        /* although you can't set ins_permuted in the constructor it might still
         * be set by memory operand folding
         * Permuting inputs of a cmov means the condition is negated!
         */
        if (attr->data.ins_permuted)
-               pnc = ia32_get_negated_pnc(pnc);
+               cc = ia32_negate_condition_code(cc);
 
        in_true  = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_true));
        in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_false));
@@ -1182,7 +1114,7 @@ static void emit_ia32_CMovcc(const ir_node *node)
 
                assert(get_ia32_op_type(node) == ia32_Normal);
 
-               pnc = ia32_get_negated_pnc(pnc);
+               cc = ia32_negate_condition_code(cc);
 
                tmp      = in_true;
                in_true  = in_false;
@@ -1192,22 +1124,11 @@ static void emit_ia32_CMovcc(const ir_node *node)
                ia32_emitf(node, "\tmovl %R, %R\n", in_false, out);
        }
 
-       /* TODO: handling of Nans isn't correct yet */
-       if (pnc & ia32_pn_Cmp_float) {
-               switch (pnc & 0x0f) {
-               case pn_Cmp_Uo:
-               case pn_Cmp_Leg:
-               case pn_Cmp_Eq:
-               case pn_Cmp_Lt:
-               case pn_Cmp_Le:
-               case pn_Cmp_Ug:
-               case pn_Cmp_Uge:
-               case pn_Cmp_Ne:
-                       panic("CMov with floatingpoint compare/parity not supported yet");
-               }
+       if (cc & ia32_cc_float_parity_cases) {
+               panic("CMov with floatingpoint compare/parity not supported yet");
        }
 
-       ia32_emitf(node, "\tcmov%P %#AR, %#R\n", pnc, in_true, out);
+       ia32_emitf(node, "\tcmov%P %#AR, %#R\n", cc, in_true, out);
 }
 
 
@@ -1244,8 +1165,7 @@ static int ia32_cmp_branch_t(const void *a, const void *b)
 static void generate_jump_table(jmp_tbl_t *tbl, const ir_node *node)
 {
        int                 i;
-       long                pnc;
-       long                default_pn;
+       long                default_pn = get_ia32_default_pn(node);
        ir_node            *proj;
        const ir_edge_t    *edge;
 
@@ -1257,26 +1177,26 @@ static void generate_jump_table(jmp_tbl_t *tbl, const ir_node *node)
        tbl->min_value    = LONG_MAX;
        tbl->max_value    = LONG_MIN;
 
-       default_pn = get_ia32_condcode(node);
        i = 0;
        /* go over all proj's and collect them */
        foreach_out_edge(node, edge) {
+               long pn;
                proj = get_edge_src_irn(edge);
                assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
 
-               pnc = get_Proj_proj(proj);
+               pn = get_Proj_proj(proj);
 
                /* check for default proj */
-               if (pnc == default_pn) {
+               if (pn == default_pn) {
                        assert(tbl->defProj == NULL && "found two default Projs at SwitchJmp");
                        tbl->defProj = proj;
                } else {
-                       tbl->min_value = pnc < tbl->min_value ? pnc : tbl->min_value;
-                       tbl->max_value = pnc > tbl->max_value ? pnc : tbl->max_value;
+                       tbl->min_value = pn < tbl->min_value ? pn : tbl->min_value;
+                       tbl->max_value = pn > tbl->max_value ? pn : tbl->max_value;
 
                        /* create branch entry */
                        tbl->branches[i].target = proj;
-                       tbl->branches[i].value  = pnc;
+                       tbl->branches[i].value  = pn;
                        ++i;
                }
 
@@ -2222,8 +2142,6 @@ static const lc_opt_table_entry_t ia32_emitter_options[] = {
 static unsigned char reg_gp_map[N_ia32_gp_REGS];
 //static unsigned char reg_mmx_map[N_ia32_mmx_REGS];
 //static unsigned char reg_sse_map[N_ia32_xmm_REGS];
-static unsigned char pnc_map_signed[8];
-static unsigned char pnc_map_unsigned[8];
 
 static void build_reg_map(void)
 {
@@ -2235,35 +2153,12 @@ static void build_reg_map(void)
        reg_gp_map[REG_GP_EBP] = 0x5;
        reg_gp_map[REG_GP_ESI] = 0x6;
        reg_gp_map[REG_GP_EDI] = 0x7;
-
-       pnc_map_signed[pn_Cmp_Eq]    = 0x04;
-       pnc_map_signed[pn_Cmp_Lt]    = 0x0C;
-       pnc_map_signed[pn_Cmp_Le]    = 0x0E;
-       pnc_map_signed[pn_Cmp_Gt]    = 0x0F;
-       pnc_map_signed[pn_Cmp_Ge]    = 0x0D;
-       pnc_map_signed[pn_Cmp_Lg]    = 0x05;
-
-       pnc_map_unsigned[pn_Cmp_Eq]    = 0x04;
-       pnc_map_unsigned[pn_Cmp_Lt]    = 0x02;
-       pnc_map_unsigned[pn_Cmp_Le]    = 0x06;
-       pnc_map_unsigned[pn_Cmp_Gt]    = 0x07;
-       pnc_map_unsigned[pn_Cmp_Ge]    = 0x03;
-       pnc_map_unsigned[pn_Cmp_Lg]    = 0x05;
 }
 
 /** Returns the encoding for a pnc field. */
-static unsigned char pnc2cc(int pnc)
+static unsigned char pnc2cc(ia32_condition_code_t cc)
 {
-       unsigned char cc;
-       if (pnc == ia32_pn_Cmp_parity) {
-               cc = 0x0A;
-       } else if (pnc & ia32_pn_Cmp_float || pnc & ia32_pn_Cmp_unsigned) {
-               cc = pnc_map_unsigned[pnc & 0x07];
-       } else {
-               cc = pnc_map_signed[pnc & 0x07];
-       }
-       assert(cc != 0);
-       return cc;
+       return cc & 0xf;
 }
 
 /** Sign extension bit values for binops */
@@ -2875,30 +2770,27 @@ static void bemit_setcc(const ir_node *node)
 {
        const arch_register_t *dreg = get_out_reg(node, pn_ia32_Setcc_res);
 
-       int pnc = get_ia32_condcode(node);
-       pnc     = determine_final_pnc(node, n_ia32_Setcc_eflags, pnc);
-       if (pnc & ia32_pn_Cmp_float) {
-               switch (pnc & 0x0f) {
-               case pn_Cmp_Uo:
-                        /* setp <dreg */
+       ia32_condition_code_t cc = get_ia32_condcode(node);
+       cc = determine_final_cc(node, n_ia32_Setcc_eflags, cc);
+       if (cc & ia32_cc_float_parity_cases) {
+               if (cc & ia32_cc_negated) {
+                       /* set%PNC <dreg */
                        bemit8(0x0F);
-                       bemit8(0x9A);
+                       bemit8(0x90 | pnc2cc(cc));
                        bemit_modrm8(REG_LOW, dreg);
-                       return;
 
-               case pn_Cmp_Leg:
-                        /* setnp <dreg*/
+                       /* setp >dreg */
                        bemit8(0x0F);
-                       bemit8(0x9B);
-                       bemit_modrm8(REG_LOW, dreg);
-                       return;
+                       bemit8(0x9A);
+                       bemit_modrm8(REG_HIGH, dreg);
 
-               case pn_Cmp_Eq:
-               case pn_Cmp_Lt:
-               case pn_Cmp_Le:
+                       /* orb %>dreg, %<dreg */
+                       bemit8(0x08);
+                       bemit_modrr8(REG_LOW, dreg, REG_HIGH, dreg);
+               } else {
                         /* set%PNC <dreg */
                        bemit8(0x0F);
-                       bemit8(0x90 | pnc2cc(pnc));
+                       bemit8(0x90 | pnc2cc(cc));
                        bemit_modrm8(REG_LOW, dreg);
 
                        /* setnp >dreg */
@@ -2909,34 +2801,13 @@ static void bemit_setcc(const ir_node *node)
                        /* andb %>dreg, %<dreg */
                        bemit8(0x20);
                        bemit_modrr8(REG_LOW, dreg, REG_HIGH, dreg);
-                       return;
-
-               case pn_Cmp_Ug:
-               case pn_Cmp_Uge:
-               case pn_Cmp_Ne:
-                       /* set%PNC <dreg */
-                       bemit8(0x0F);
-                       bemit8(0x90 | pnc2cc(pnc));
-                       bemit_modrm8(REG_LOW, dreg);
-
-                       /* setp >dreg */
-                       bemit8(0x0F);
-                       bemit8(0x9A);
-                       bemit_modrm8(REG_HIGH, dreg);
-
-                       /* orb %>dreg, %<dreg */
-                       bemit8(0x08);
-                       bemit_modrr8(REG_LOW, dreg, REG_HIGH, dreg);
-                       return;
-
-               default:
-                       break;
                }
+       } else {
+               /* set%PNC <dreg */
+               bemit8(0x0F);
+               bemit8(0x90 | pnc2cc(cc));
+               bemit_modrm8(REG_LOW, dreg);
        }
-       /* set%PNC <dreg */
-       bemit8(0x0F);
-       bemit8(0x90 | pnc2cc(pnc));
-       bemit_modrm8(REG_LOW, dreg);
 }
 
 static void bemit_cmovcc(const ir_node *node)
@@ -2944,11 +2815,11 @@ static void bemit_cmovcc(const ir_node *node)
        const ia32_attr_t     *attr         = get_ia32_attr_const(node);
        int                    ins_permuted = attr->data.ins_permuted;
        const arch_register_t *out          = arch_irn_get_register(node, pn_ia32_res);
-       int                    pnc          = get_ia32_condcode(node);
+       ia32_condition_code_t  cc           = get_ia32_condcode(node);
        const arch_register_t *in_true;
        const arch_register_t *in_false;
 
-       pnc = determine_final_pnc(node, n_ia32_CMovcc_eflags, pnc);
+       cc = determine_final_cc(node, n_ia32_CMovcc_eflags, cc);
 
        in_true  = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_true));
        in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_false));
@@ -2967,12 +2838,13 @@ static void bemit_cmovcc(const ir_node *node)
        }
 
        if (ins_permuted)
-               pnc = ia32_get_negated_pnc(pnc);
+               cc = ia32_negate_condition_code(cc);
 
-       /* TODO: handling of Nans isn't correct yet */
+       if (cc & ia32_cc_float_parity_cases)
+               panic("cmov can't handle parity float cases");
 
        bemit8(0x0F);
-       bemit8(0x40 | pnc2cc(pnc));
+       bemit8(0x40 | pnc2cc(cc));
        if (get_ia32_op_type(node) == ia32_Normal) {
                bemit_modrr(in_true, out);
        } else {
@@ -3500,14 +3372,14 @@ static void bemit_jp(bool odd, const ir_node *dest_block)
 
 static void bemit_ia32_jcc(const ir_node *node)
 {
-       int            pnc = get_ia32_condcode(node);
-       const ir_node *proj_true;
-       const ir_node *proj_false;
-       const ir_node *dest_true;
-       const ir_node *dest_false;
-       const ir_node *block;
+       ia32_condition_code_t cc = get_ia32_condcode(node);
+       const ir_node        *proj_true;
+       const ir_node        *proj_false;
+       const ir_node        *dest_true;
+       const ir_node        *dest_false;
+       const ir_node        *block;
 
-       pnc = determine_final_pnc(node, 0, pnc);
+       cc = determine_final_cc(node, 0, cc);
 
        /* get both Projs */
        proj_true = get_proj(node, pn_ia32_Jcc_true);
@@ -3524,51 +3396,29 @@ static void bemit_ia32_jcc(const ir_node *node)
 
                proj_true  = proj_false;
                proj_false = t;
-               pnc        = ia32_get_negated_pnc(pnc);
+               cc         = ia32_negate_condition_code(cc);
        }
 
        dest_true  = get_cfop_target_block(proj_true);
        dest_false = get_cfop_target_block(proj_false);
 
-       if (pnc & ia32_pn_Cmp_float) {
+       if (cc & ia32_cc_float_parity_cases) {
                /* Some floating point comparisons require a test of the parity flag,
                 * which indicates that the result is unordered */
-               switch (pnc & 15) {
-                       case pn_Cmp_Uo: {
-                               bemit_jp(false, dest_true);
-                               break;
+               if (cc & ia32_cc_negated) {
+                       bemit_jp(false, dest_true);
+               } else {
+                       /* we need a local label if the false proj is a fallthrough
+                        * as the falseblock might have no label emitted then */
+                       if (can_be_fallthrough(proj_false)) {
+                               bemit8(0x7A);
+                               bemit8(0x06);  // jp + 6
+                       } else {
+                               bemit_jp(false, dest_false);
                        }
-
-                       case pn_Cmp_Leg:
-                               bemit_jp(true, dest_true);
-                               break;
-
-                       case pn_Cmp_Eq:
-                       case pn_Cmp_Lt:
-                       case pn_Cmp_Le:
-                               /* we need a local label if the false proj is a fallthrough
-                                * as the falseblock might have no label emitted then */
-                               if (can_be_fallthrough(proj_false)) {
-                                       bemit8(0x7A);
-                                       bemit8(0x06);  // jp + 6
-                               } else {
-                                       bemit_jp(false, dest_false);
-                               }
-                               goto emit_jcc;
-
-                       case pn_Cmp_Ug:
-                       case pn_Cmp_Uge:
-                       case pn_Cmp_Ne:
-                               bemit_jp(false, dest_true);
-                               goto emit_jcc;
-
-                       default:
-                               goto emit_jcc;
                }
-       } else {
-emit_jcc:
-               bemit_jcc(pnc, dest_true);
        }
+       bemit_jcc(cc, dest_true);
 
        /* the second Proj might be a fallthrough */
        if (can_be_fallthrough(proj_false)) {
index 0c3805a..cf33b5e 100644 (file)
@@ -29,6 +29,7 @@
 #include "config.h"
 
 #include <stdlib.h>
+#include <stdbool.h>
 
 #include "irargs_t.h"
 #include "irprog_t.h"
@@ -185,14 +186,11 @@ static void ia32_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
 
                        /* dump pn code */
                        if (is_ia32_SwitchJmp(n)) {
-                               fprintf(F, "pn_code = %ld\n", get_ia32_condcode(n));
+                               fprintf(F, "default_pn = %ld\n", get_ia32_default_pn(n));
                        } else if (is_ia32_CMovcc(n) || is_ia32_Setcc(n) || is_ia32_Jcc(n)) {
                                ia32_attr_t *attr = get_ia32_attr(n);
-                               long pnc = get_ia32_condcode(n);
-                               fprintf(F, "pn_code = 0x%X (%s)\n", (unsigned) pnc,
-                                       get_pnc_string(pnc & pn_Cmp_True));
+                               fprintf(F, "condition_code = 0x%X\n", get_ia32_condcode(n));
                                fprintf(F, "ins_permuted = %u \n", attr->data.ins_permuted);
-                               fprintf(F, "cmp_unsigned = %u \n", attr->data.cmp_unsigned);
                        }
                        else if (is_ia32_CopyB(n) || is_ia32_CopyB_i(n)) {
                                fprintf(F, "size = %u\n", get_ia32_copyb_size(n));
@@ -308,6 +306,20 @@ const ia32_condcode_attr_t *get_ia32_condcode_attr_const(const ir_node *node)
        return cc_attr;
 }
 
+ia32_switch_attr_t *get_ia32_switch_attr(ir_node *node)
+{
+       ia32_attr_t        *attr        = get_ia32_attr(node);
+       ia32_switch_attr_t *switch_attr = CAST_IA32_ATTR(ia32_switch_attr_t, attr);
+       return switch_attr;
+}
+
+const ia32_switch_attr_t *get_ia32_switch_attr_const(const ir_node *node)
+{
+       const ia32_attr_t        *attr        = get_ia32_attr_const(node);
+       const ia32_switch_attr_t *switch_attr = CONST_CAST_IA32_ATTR(ia32_switch_attr_t, attr);
+       return switch_attr;
+}
+
 ia32_call_attr_t *get_ia32_call_attr(ir_node *node)
 {
        ia32_attr_t      *attr      = get_ia32_attr(node);
@@ -652,19 +664,25 @@ unsigned get_ia32_latency(const ir_node *node)
 /**
  * Returns the condition code of a node.
  */
-long get_ia32_condcode(const ir_node *node)
+ia32_condition_code_t get_ia32_condcode(const ir_node *node)
 {
        const ia32_condcode_attr_t *attr = get_ia32_condcode_attr_const(node);
-       return attr->pn_code;
+       return attr->condition_code;
 }
 
 /**
  * Sets the condition code of a node
  */
-void set_ia32_condcode(ir_node *node, long code)
+void set_ia32_condcode(ir_node *node, ia32_condition_code_t code)
 {
        ia32_condcode_attr_t *attr = get_ia32_condcode_attr(node);
-       attr->pn_code = code;
+       attr->condition_code = code;
+}
+
+long get_ia32_default_pn(const ir_node *node)
+{
+       const ia32_switch_attr_t *attr = get_ia32_switch_attr_const(node);
+       return attr->default_pn;
 }
 
 /**
@@ -874,14 +892,14 @@ void init_ia32_copyb_attributes(ir_node *res, unsigned size)
        attr->size = size;
 }
 
-void init_ia32_condcode_attributes(ir_node *res, long pnc)
+void init_ia32_condcode_attributes(ir_node *res, ia32_condition_code_t cc)
 {
        ia32_condcode_attr_t *attr = (ia32_condcode_attr_t*)get_irn_generic_attr(res);
 
 #ifndef NDEBUG
        attr->attr.attr_type  |= IA32_ATTR_ia32_condcode_attr_t;
 #endif
-       attr->pn_code = pnc;
+       attr->condition_code = cc;
 }
 
 void init_ia32_climbframe_attributes(ir_node *res, unsigned count)
@@ -894,6 +912,15 @@ void init_ia32_climbframe_attributes(ir_node *res, unsigned count)
        attr->count = count;
 }
 
+void init_ia32_switch_attributes(ir_node *res, long default_pn)
+{
+       ia32_switch_attr_t *attr = (ia32_switch_attr_t*) get_irn_generic_attr(res);
+#ifndef NDEBUG
+       attr->attr.attr_type |= IA32_ATTR_ia32_switch_attr_t;
+#endif
+       attr->default_pn = default_pn;
+}
+
 
 /* default compare operation to compare attributes */
 static int ia32_compare_attr(const ia32_attr_t *a, const ia32_attr_t *b)
@@ -923,8 +950,7 @@ static int ia32_compare_attr(const ia32_attr_t *a, const ia32_attr_t *b)
        if (a->data.has_except_label != b->data.has_except_label)
                return 1;
 
-       if (a->data.ins_permuted != b->data.ins_permuted
-                       || a->data.cmp_unsigned != b->data.cmp_unsigned)
+       if (a->data.ins_permuted != b->data.ins_permuted)
                return 1;
 
        return 0;
@@ -951,7 +977,25 @@ static int ia32_compare_condcode_attr(ir_node *a, ir_node *b)
        attr_a = get_ia32_condcode_attr_const(a);
        attr_b = get_ia32_condcode_attr_const(b);
 
-       if (attr_a->pn_code != attr_b->pn_code)
+       if (attr_a->condition_code != attr_b->condition_code)
+               return 1;
+
+       return 0;
+}
+
+/** Compare node attributes for nodes with condition code. */
+static int ia32_compare_switch_attr(ir_node *a, ir_node *b)
+{
+       const ia32_switch_attr_t *attr_a;
+       const ia32_switch_attr_t *attr_b;
+
+       if (ia32_compare_nodes_attr(a, b))
+               return 1;
+
+       attr_a = get_ia32_switch_attr_const(a);
+       attr_b = get_ia32_switch_attr_const(b);
+
+       if (attr_a->default_pn != attr_b->default_pn)
                return 1;
 
        return 0;
index 81b6d0c..ad0ce48 100644 (file)
@@ -244,16 +244,15 @@ void set_ia32_frame_ent(ir_node *node, ir_entity *ent);
 /**
  * Returns the condition code of a node.
  */
-long get_ia32_condcode(const ir_node *node);
+ia32_condition_code_t get_ia32_condcode(const ir_node *node);
 
 /**
  * Sets the condition code of a node
  */
-void set_ia32_condcode(ir_node *node, long code);
+void set_ia32_condcode(ir_node *node, ia32_condition_code_t code);
+
+long get_ia32_default_pn(const ir_node *node);
 
-/**
- * Returns the condition code of a node.
- */
 unsigned get_ia32_copyb_size(const ir_node *node);
 
 /**
@@ -327,7 +326,7 @@ int is_ia32_AddrModeS(const ir_node *node);
 int is_ia32_AddrModeD(const ir_node *node);
 
 /**
- * Swaps left/right input of a node (and adjusts pnc if needed)
+ * Swaps left/right input of a node (and sets ins_permuted accordingly)
  */
 void ia32_swap_left_right(ir_node *node);
 
@@ -346,7 +345,7 @@ void init_ia32_immediate_attributes(ir_node *node, ir_entity *symconst,
                                                                        long offset);
 void init_ia32_call_attributes(ir_node *res, unsigned pop, ir_type *call_tp);
 void init_ia32_copyb_attributes(ir_node *res, unsigned size);
-void init_ia32_condcode_attributes(ir_node *res, long pnc);
+void init_ia32_condcode_attributes(ir_node *res, ia32_condition_code_t cc);
 void init_ia32_climbframe_attributes(ir_node *res, unsigned count);
 
 /* Include the generated headers */
index 5df9484..4d80a88 100644 (file)
 #include "../bemachine.h"
 #include "irnode_t.h"
 
-enum {
-       ia32_pn_Cmp_unsigned  = 0x1000,
-       ia32_pn_Cmp_float     = 0x2000,
-       ia32_pn_Cmp_parity    = 0x4000,
-       /* The unsigned Lt/Ge comparisons test the carry bit. */
-       ia32_pn_Cmp_carry     = pn_Cmp_Lt | ia32_pn_Cmp_unsigned,
-       ia32_pn_Cmp_not_carry = pn_Cmp_Ge | ia32_pn_Cmp_unsigned
-};
+/** ia32 condition codes (the numbers correspond to the real encoding order) */
+typedef enum ia32_condition_code_t {
+       ia32_cc_negated       = 0x01, /**< negates condition */
+
+       ia32_cc_overflow      = 0x00,                                /**< OF=1 */
+       ia32_cc_below         = 0x02,                                /**< CF=1 */
+       ia32_cc_equal         = 0x04,                                /**< ZF=1 */
+       ia32_cc_below_equal   = 0x06,                                /**< ZF=1 or CF=1 */
+       ia32_cc_sign          = 0x08,                                /**< SF=1 */
+       ia32_cc_parity        = 0x0A,                                /**< PF=1 */
+       ia32_cc_less          = 0x0C,                                /**< SF!=OF */
+       ia32_cc_less_equal    = 0x0E,                                /**< ZF=1 or SF!=OF */
+       ia32_cc_not_overflow  = ia32_cc_negated|ia32_cc_overflow,    /**< OF=0 */
+       ia32_cc_above_equal   = ia32_cc_negated|ia32_cc_below,       /**< CF=0 */
+       ia32_cc_not_equal     = ia32_cc_negated|ia32_cc_equal,       /**< ZF=0 */
+       ia32_cc_above         = ia32_cc_negated|ia32_cc_below_equal, /**< ZF=0 and CF=0 */
+       ia32_cc_not_sign      = ia32_cc_negated|ia32_cc_sign,        /**< SF=0 */
+       ia32_cc_not_parity    = ia32_cc_negated|ia32_cc_parity,      /**< PF=0 */
+       ia32_cc_greater_equal = ia32_cc_negated|ia32_cc_less,        /**< SF=OF */
+       ia32_cc_greater       = ia32_cc_negated|ia32_cc_less_equal,  /**< ZF=0 and SF=OF */
+
+       /* the following codes are (unfortunately) NOT real hardware codes but
+        * simplify our backend as you need these combinations for some
+        * floatingpoint compares (the emitter will split them into multiple
+        * instructions) */
+       ia32_cc_float_parity_cases = 0x20,
+       /* we need even more cases as inversing the cc is different for float
+        * comparisons (though for the following we need no special
+        * parity+x combinations) */
+       ia32_cc_additional_float_cases = 0x10,
+
+       /* make sure that the lower 4 bit correspond to the real encoding
+        * (of the comparison not involving the parity special) */
+       ia32_cc_float_equal        = 0x34,                                /**< PF=0 and ZF=1 */
+       ia32_cc_float_below        = 0x32,                                /**< PF=0 and CF=1 */
+       ia32_cc_float_below_equal  = 0x36,                                /**< PF=0 and (ZF=1 or CF=1) */
+       ia32_cc_float_not_equal    = ia32_cc_negated|ia32_cc_float_equal, /**< PF=1 or ZF=0 */
+       ia32_cc_float_unordered_above_equal
+               = ia32_cc_negated|ia32_cc_float_below,                        /**< PF=1 or CF=0 */
+       ia32_cc_float_unordered_above
+               = ia32_cc_negated|ia32_cc_float_below_equal,                  /**< PF=1 or (ZF=0 and CF=0) */
+
+       ia32_cc_float_unordered_below_equal = 0x16,                       /**< ZF=1 or CF=1 */
+       ia32_cc_float_unordered_below       = 0x12,                       /**< CF=1 */
+       ia32_cc_float_above        =
+               ia32_cc_negated|ia32_cc_float_unordered_below_equal,          /**< ZF=0 and CF=0 */
+       ia32_cc_float_above_equal
+               = ia32_cc_negated|ia32_cc_float_unordered_below,              /**< CF=0 */
+} ia32_condition_code_t;
+ENUM_BITSET(ia32_condition_code_t)
+
+static inline ia32_condition_code_t ia32_negate_condition_code(
+               ia32_condition_code_t code)
+{
+       return code ^ ia32_cc_negated;
+}
+
+static inline ia32_condition_code_t ia32_invert_condition_code(
+               ia32_condition_code_t code)
+{
+       /* doesn't appear to have any systematic, so use a table */
+       switch (code) {
+       case ia32_cc_below:              return ia32_cc_above;
+       case ia32_cc_below_equal:        return ia32_cc_above_equal;
+       case ia32_cc_above:              return ia32_cc_below;
+       case ia32_cc_above_equal:        return ia32_cc_below_equal;
+       case ia32_cc_less:               return ia32_cc_greater;
+       case ia32_cc_less_equal:         return ia32_cc_greater_equal;
+       case ia32_cc_greater:            return ia32_cc_less;
+       case ia32_cc_greater_equal:      return ia32_cc_less_equal;
+       case ia32_cc_float_below:        return ia32_cc_float_above;
+       case ia32_cc_float_below_equal:  return ia32_cc_float_above_equal;
+       case ia32_cc_float_above:        return ia32_cc_float_below;
+       case ia32_cc_float_above_equal:  return ia32_cc_float_below_equal;
+       case ia32_cc_float_unordered_below:       return ia32_cc_float_unordered_above;
+       case ia32_cc_float_unordered_below_equal: return ia32_cc_float_unordered_above_equal;
+       case ia32_cc_float_unordered_above:       return ia32_cc_float_unordered_below;
+       case ia32_cc_float_unordered_above_equal: return ia32_cc_float_unordered_below_equal;
+       default:                         return code;
+       }
+}
 
 typedef enum {
        ia32_Normal,
@@ -87,6 +160,7 @@ typedef enum {
        IA32_ATTR_ia32_copyb_attr_t      = 1 << 5,
        IA32_ATTR_ia32_call_attr_t       = 1 << 6,
        IA32_ATTR_ia32_climbframe_attr_t = 1 << 7,
+       IA32_ATTR_ia32_switch_attr_t     = 1 << 8,
 } ia32_attr_type_t;
 #endif
 
@@ -113,7 +187,6 @@ struct ia32_attr_t {
                unsigned need_32bit_stackent:1; /**< needs a 32bit stack entity */
                unsigned ins_permuted : 1;      /**< inputs of node have been permuted
                                                     (for commutative nodes) */
-               unsigned cmp_unsigned : 1;      /**< compare should be unsigned */
                unsigned is_reload : 1;         /**< node performs a reload */
                unsigned is_spill : 1;
                unsigned is_remat : 1;
@@ -152,8 +225,17 @@ struct ia32_call_attr_t {
  */
 typedef struct ia32_condcode_attr_t ia32_condcode_attr_t;
 struct ia32_condcode_attr_t {
-       ia32_attr_t  attr;      /**< generic attribute */
-       long         pn_code;   /**< projnum "types" (e.g. indicate compare operators */
+       ia32_attr_t           attr;           /**< generic attribute */
+       ia32_condition_code_t condition_code; /**< condition code*/
+};
+
+/**
+ * The attributes for Switches
+ */
+typedef struct ia32_switch_attr_t ia32_switch_attr_t;
+struct ia32_switch_attr_t {
+       ia32_attr_t  attr;        /**< generic attribute */
+       long         default_pn;
 };
 
 /**
@@ -227,6 +309,7 @@ union allow_casts_attr_t_ {
        ia32_asm_attr_t        asm_attr;
        ia32_immediate_attr_t  immediate_attr;
        ia32_climbframe_attr_t climbframe_attr;
+       ia32_switch_attr_t     switch_attr;
 };
 
 #ifndef NDEBUG
index 963d9b1..71ce6f7 100644 (file)
@@ -153,7 +153,6 @@ static void peephole_ia32_Cmp(ir_node *const node)
        ir_node                     *op;
        ia32_attr_t           const *attr;
        int                          ins_permuted;
-       int                          cmp_unsigned;
        ir_node                     *test;
        arch_register_t       const *reg;
        ir_edge_t             const *edge;
@@ -178,14 +177,13 @@ static void peephole_ia32_Cmp(ir_node *const node)
        op           = get_irn_n(node, n_ia32_Cmp_left);
        attr         = get_ia32_attr(node);
        ins_permuted = attr->data.ins_permuted;
-       cmp_unsigned = attr->data.cmp_unsigned;
 
        if (is_ia32_Cmp(node)) {
                test = new_bd_ia32_Test(dbgi, block, noreg, noreg, nomem,
-                                       op, op, ins_permuted, cmp_unsigned);
+                                       op, op, ins_permuted);
        } else {
                test = new_bd_ia32_Test8Bit(dbgi, block, noreg, noreg, nomem,
-                                           op, op, ins_permuted, cmp_unsigned);
+                                           op, op, ins_permuted);
        }
        set_ia32_ls_mode(test, get_ia32_ls_mode(node));
 
@@ -248,10 +246,10 @@ static void peephole_ia32_Test(ir_node *node)
 
                /* make sure only Lg/Eq tests are used */
                foreach_out_edge(node, edge) {
-                       ir_node *user = get_edge_src_irn(edge);
-                       int      pnc  = get_ia32_condcode(user);
+                       ir_node              *user = get_edge_src_irn(edge);
+                       ia32_condition_code_t cc  = get_ia32_condcode(user);
 
-                       if (pnc != pn_Cmp_Eq && pnc != pn_Cmp_Lg) {
+                       if (cc != ia32_cc_equal && cc != ia32_cc_not_equal) {
                                return;
                        }
                }
@@ -262,15 +260,15 @@ static void peephole_ia32_Test(ir_node *node)
 
                        case produces_flag_carry:
                                foreach_out_edge(node, edge) {
-                                       ir_node *user = get_edge_src_irn(edge);
-                                       int      pnc  = get_ia32_condcode(user);
+                                       ir_node              *user = get_edge_src_irn(edge);
+                                       ia32_condition_code_t cc   = get_ia32_condcode(user);
 
-                                       switch (pnc) {
-                                               case pn_Cmp_Eq: pnc = ia32_pn_Cmp_not_carry; break;
-                                               case pn_Cmp_Lg: pnc = ia32_pn_Cmp_carry;     break;
-                                               default: panic("unexpected pn");
+                                       switch (cc) {
+                                       case ia32_cc_equal:     cc = ia32_cc_above_equal; break; /* CF = 0 */
+                                       case ia32_cc_not_equal: cc = ia32_cc_below;       break; /* CF = 1 */
+                                       default: panic("unexpected pn");
                                        }
-                                       set_ia32_condcode(user, pnc);
+                                       set_ia32_condcode(user, cc);
                                }
                                break;
 
index a08ec26..fddc1bb 100644 (file)
@@ -177,7 +177,10 @@ $custom_init_attr_func = \&ia32_custom_init_attr;
                "\tinit_ia32_call_attributes(res, pop, call_tp);",
        ia32_condcode_attr_t =>
                "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
-               "\tinit_ia32_condcode_attributes(res, pnc);",
+               "\tinit_ia32_condcode_attributes(res, condition_code);",
+       ia32_switch_attr_t =>
+               "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
+               "\tinit_ia32_switch_attributes(res, default_pn);",
        ia32_copyb_attr_t =>
                "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
                "\tinit_ia32_copyb_attributes(res, size);",
@@ -193,10 +196,11 @@ $custom_init_attr_func = \&ia32_custom_init_attr;
 );
 
 %compare_attr = (
-       ia32_asm_attr_t       => "ia32_compare_asm_attr",
+       ia32_asm_attr_t        => "ia32_compare_asm_attr",
        ia32_attr_t            => "ia32_compare_nodes_attr",
        ia32_call_attr_t       => "ia32_compare_call_attr",
        ia32_condcode_attr_t   => "ia32_compare_condcode_attr",
+       ia32_switch_attr_t     => "ia32_compare_switch_attr",
        ia32_copyb_attr_t      => "ia32_compare_copyb_attr",
        ia32_immediate_attr_t  => "ia32_compare_immediate_attr",
        ia32_x87_attr_t        => "ia32_compare_x87_attr",
@@ -932,9 +936,8 @@ Cmp => {
        outs      => [ "eflags", "unused", "M" ],
        am        => "source,binary",
        emit      => '. cmp%M %binop',
-       attr      => "int ins_permuted, int cmp_unsigned",
-       init_attr => "attr->data.ins_permuted   = ins_permuted;\n".
-                    "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
+       attr      => "bool ins_permuted",
+       init_attr => "attr->data.ins_permuted   = ins_permuted;",
        latency   => 1,
        units     => [ "GP" ],
        mode      => $mode_flags,
@@ -950,9 +953,8 @@ Cmp8Bit => {
        outs      => [ "eflags", "unused", "M" ],
        am        => "source,binary",
        emit      => '. cmpb %binop',
-       attr      => "int ins_permuted, int cmp_unsigned",
-       init_attr => "attr->data.ins_permuted   = ins_permuted;\n".
-                    "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
+       attr      => "bool ins_permuted",
+       init_attr => "attr->data.ins_permuted   = ins_permuted;",
        latency   => 1,
        units     => [ "GP" ],
        mode      => $mode_flags,
@@ -968,9 +970,8 @@ Test => {
        outs      => [ "eflags", "unused", "M" ],
        am        => "source,binary",
        emit      => '. test%M %binop',
-       attr      => "int ins_permuted, int cmp_unsigned",
-       init_attr => "attr->data.ins_permuted = ins_permuted;\n".
-                    "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
+       attr      => "bool ins_permuted",
+       init_attr => "attr->data.ins_permuted = ins_permuted;",
        latency   => 1,
        units     => [ "GP" ],
        mode      => $mode_flags,
@@ -986,9 +987,8 @@ Test8Bit => {
        outs      => [ "eflags", "unused", "M" ],
        am        => "source,binary",
        emit      => '. testb %binop',
-       attr      => "int ins_permuted, int cmp_unsigned",
-       init_attr => "attr->data.ins_permuted = ins_permuted;\n".
-                    "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
+       attr      => "bool ins_permuted",
+       init_attr => "attr->data.ins_permuted = ins_permuted;",
        latency   => 1,
        units     => [ "GP" ],
        mode      => $mode_flags,
@@ -1001,11 +1001,11 @@ Setcc => {
        ins       => [ "eflags" ],
        outs      => [ "res" ],
        attr_type => "ia32_condcode_attr_t",
-       attr      => "int pnc",
+       attr      => "ia32_condition_code_t condition_code",
        # The way we handle Setcc with float nodes (potentially) destroys the flags
        # (when we emit the setX; setp; orb and the setX;setnp;andb sequences)
        init_attr => "set_ia32_ls_mode(res, mode_Bu);\n"
-               . "\tif ((pnc & ia32_pn_Cmp_float) && ((pnc & 0xf) != pn_Cmp_Uo) && ((pnc & 0xf) != pn_Cmp_Leg)) {\n"
+               . "\tif (condition_code & ia32_cc_additional_float_cases) {\n"
                . "\t\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);\n"
                . "\t\t/* attr->latency = 3; */\n"
                . "\t}\n",
@@ -1020,7 +1020,7 @@ SetccMem => {
        reg_req   => { in => [ "gp", "gp", "none", "eflags" ], out => [ "none" ] },
        ins       => [ "base", "index", "mem","eflags" ],
        attr_type => "ia32_condcode_attr_t",
-       attr      => "int pnc",
+       attr      => "ia32_condition_code_t condition_code",
        init_attr => "set_ia32_ls_mode(res, mode_Bu);\n",
        emit      => '. set%CMP3 %AM',
        latency   => 1,
@@ -1039,7 +1039,7 @@ CMovcc => {
        outs      => [ "res", "flags", "M" ],
        am        => "source,binary",
        attr_type => "ia32_condcode_attr_t",
-       attr      => "int pnc",
+       attr      => "ia32_condition_code_t condition_code",
        latency   => 1,
        units     => [ "GP" ],
        mode      => $mode_gp,
@@ -1052,7 +1052,7 @@ Jcc => {
        ins       => [ "eflags" ],
        outs      => [ "false", "true" ],
        attr_type => "ia32_condcode_attr_t",
-       attr      => "int pnc",
+       attr      => "ia32_condition_code_t condition_code",
        latency   => 2,
        units     => [ "BRANCH" ],
 },
@@ -1062,8 +1062,8 @@ SwitchJmp => {
        op_flags  => [ "labeled", "cfopcode", "forking" ],
        reg_req   => { in => [ "gp" ] },
        mode      => "mode_T",
-       attr_type => "ia32_condcode_attr_t",
-       attr      => "long pnc",
+       attr_type => "ia32_switch_attr_t",
+       attr      => "long default_pn",
        latency   => 3,
        units     => [ "BRANCH" ],
        modified_flags => $status_flags,
@@ -1849,7 +1849,7 @@ Ucomi => {
        ins       => [ "base", "index", "mem", "left", "right" ],
        outs      => [ "flags" ],
        am        => "source,binary",
-       attr      => "int ins_permuted",
+       attr      => "bool ins_permuted",
        init_attr => "attr->data.ins_permuted = ins_permuted;",
        emit      => ' .ucomi%XXM %binop',
        latency   => 3,
@@ -2258,7 +2258,7 @@ vFucomFnstsw => {
        reg_req   => { in => [ "vfp", "vfp" ], out => [ "eax" ] },
        ins       => [ "left", "right" ],
        outs      => [ "flags" ],
-       attr      => "int ins_permuted",
+       attr      => "bool ins_permuted",
        init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
        latency   => 3,
        units     => [ "VFP" ],
@@ -2271,7 +2271,7 @@ vFucomi => {
        reg_req   => { in => [ "vfp", "vfp" ], out => [ "eflags" ] },
        ins       => [ "left", "right" ],
        outs      => [ "flags" ],
-       attr      => "int ins_permuted",
+       attr      => "bool ins_permuted",
        init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
        latency   => 3,
        units     => [ "VFP" ],
@@ -2284,7 +2284,7 @@ vFtstFnstsw => {
        reg_req   => { in => [ "vfp" ], out => [ "eax" ] },
        ins       => [ "left" ],
        outs      => [ "flags" ],
-       attr      => "int ins_permuted",
+       attr      => "bool ins_permuted",
        init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
        latency   => 3,
        units     => [ "VFP" ],
index 6e16287..e3cad31 100644 (file)
@@ -871,7 +871,7 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block,
                } else {
                        new_op1 = be_transform_node(op2);
                        new_op2 = noreg;
-                       am->ins_permuted = 1;
+                       am->ins_permuted = true;
                }
                am->op_type = ia32_AddrModeS;
        } else {
@@ -1907,81 +1907,151 @@ static ir_node *gen_bt(ir_node *cmp, ir_node *x, ir_node *n)
        return new_bd_ia32_Bt(dbgi, new_block, op1, op2);
 }
 
-/**
- * Transform a node returning a "flag" result.
- *
- * @param node     the node to transform
- * @param pnc_out  the compare mode to use
- */
-static ir_node *get_flags_node(ir_node *node, int *pnc_out)
+static ia32_condition_code_t pnc_to_condition_code(pn_Cmp pnc, ir_mode *mode)
 {
+       if (mode_is_float(mode)) {
+               switch (pnc) {
+               case pn_Cmp_Eq:  return ia32_cc_float_equal;
+               case pn_Cmp_Lt:  return ia32_cc_float_below;
+               case pn_Cmp_Le:  return ia32_cc_float_below_equal;
+               case pn_Cmp_Gt:  return ia32_cc_float_above;
+               case pn_Cmp_Ge:  return ia32_cc_float_above_equal;
+               case pn_Cmp_Lg:  return ia32_cc_not_equal;
+               case pn_Cmp_Leg: return ia32_cc_not_parity;
+               case pn_Cmp_Uo:  return ia32_cc_parity;
+               case pn_Cmp_Ue:  return ia32_cc_equal;
+               case pn_Cmp_Ul:  return ia32_cc_float_unordered_below;
+               case pn_Cmp_Ule: return ia32_cc_float_unordered_below_equal;
+               case pn_Cmp_Ug:  return ia32_cc_float_unordered_above;
+               case pn_Cmp_Uge: return ia32_cc_float_unordered_above_equal;
+               case pn_Cmp_Ne:  return ia32_cc_float_not_equal;
+               case pn_Cmp_False:
+               case pn_Cmp_True:
+               case pn_Cmp_max:
+                       /* should we introduce a jump always/jump never? */
+                       break;
+               }
+               panic("Unexpected float pnc");
+       } else if (mode_is_signed(mode)) {
+               switch (pnc) {
+               case pn_Cmp_Ue:
+               case pn_Cmp_Eq:  return ia32_cc_equal;
+               case pn_Cmp_Ul:
+               case pn_Cmp_Lt:  return ia32_cc_less;
+               case pn_Cmp_Ule:
+               case pn_Cmp_Le:  return ia32_cc_less_equal;
+               case pn_Cmp_Ug:
+               case pn_Cmp_Gt:  return ia32_cc_greater;
+               case pn_Cmp_Uge:
+               case pn_Cmp_Ge:  return ia32_cc_greater_equal;
+               case pn_Cmp_Lg:
+               case pn_Cmp_Ne:  return ia32_cc_not_equal;
+               case pn_Cmp_Leg:
+               case pn_Cmp_Uo:
+               case pn_Cmp_False:
+               case pn_Cmp_True:
+               case pn_Cmp_max:
+                       /* introduce jump always/jump never? */
+                       break;
+               }
+               panic("Unexpected pnc");
+       } else {
+               switch (pnc) {
+               case pn_Cmp_Ue:
+               case pn_Cmp_Eq:  return ia32_cc_equal;
+               case pn_Cmp_Ul:
+               case pn_Cmp_Lt:  return ia32_cc_below;
+               case pn_Cmp_Ule:
+               case pn_Cmp_Le:  return ia32_cc_below_equal;
+               case pn_Cmp_Ug:
+               case pn_Cmp_Gt:  return ia32_cc_above;
+               case pn_Cmp_Uge:
+               case pn_Cmp_Ge:  return ia32_cc_above_equal;
+               case pn_Cmp_Lg:
+               case pn_Cmp_Ne:  return ia32_cc_not_equal;
+               case pn_Cmp_Leg:
+               case pn_Cmp_Uo:
+               case pn_Cmp_False:
+               case pn_Cmp_True:
+               case pn_Cmp_max:
+                       /* introduce jump always/jump never? */
+                       break;
+               }
+               panic("Unexpected pnc");
+       }
+}
+
+static ir_node *get_flags_mode_b(ir_node *node, ia32_condition_code_t *cc_out)
+{
+       /* a mode_b value, we have to compare it against 0 */
+       dbg_info *dbgi      = get_irn_dbg_info(node);
+       ir_node  *new_block = be_transform_node(get_nodes_block(node));
+       ir_node  *new_op    = be_transform_node(node);
+       ir_node  *flags     = new_bd_ia32_Test(dbgi, new_block, noreg_GP, noreg_GP, nomem, new_op, new_op, false);
+       *cc_out  = ia32_cc_not_equal;
+       return flags;
+}
+
+static ir_node *get_flags_node_cmp(ir_node *node, ia32_condition_code_t *cc_out)
+{
+       /* must have a Proj(Cmp) as input */
+       ir_node  *cmp  = get_Proj_pred(node);
+       int       pnc  = get_Proj_pn_cmp(node);
+       ir_node  *l    = get_Cmp_left(cmp);
+       ir_mode  *mode = get_irn_mode(l);
        ir_node  *flags;
-       ir_node  *new_op;
-       ir_node  *new_block;
-       dbg_info *dbgi;
 
-       /* we have a Cmp as input */
-       if (is_Proj(node)) {
-               ir_node *pred = get_Proj_pred(node);
-               if (is_Cmp(pred)) {
-                       int pnc = get_Proj_pn_cmp(node);
-                       if (ia32_cg_config.use_bt && (pnc == pn_Cmp_Lg || pnc == pn_Cmp_Eq)) {
-                               ir_node *l = get_Cmp_left(pred);
-                               ir_node *r = get_Cmp_right(pred);
-                               if (is_And(l)) {
-                                       ir_node *la = get_And_left(l);
-                                       ir_node *ra = get_And_right(l);
-                                       if (is_Shl(la)) {
-                                               ir_node *c = get_Shl_left(la);
-                                               if (is_Const_1(c) && is_Const_0(r)) {
-                                                       /* (1 << n) & ra) */
-                                                       ir_node *n = get_Shl_right(la);
-                                                       flags    = gen_bt(pred, ra, n);
-                                                       /* we must generate a Jc/Jnc jump */
-                                                       pnc = pnc == pn_Cmp_Lg ? pn_Cmp_Lt : pn_Cmp_Ge;
-                                                       *pnc_out = ia32_pn_Cmp_unsigned | pnc;
-                                                       return flags;
-                                               }
-                                       }
-                                       if (is_Shl(ra)) {
-                                               ir_node *c = get_Shl_left(ra);
-                                               if (is_Const_1(c) && is_Const_0(r)) {
-                                                       /* la & (1 << n)) */
-                                                       ir_node *n = get_Shl_right(ra);
-                                                       flags    = gen_bt(pred, la, n);
-                                                       /* we must generate a Jc/Jnc jump */
-                                                       pnc = pnc == pn_Cmp_Lg ? pn_Cmp_Lt : pn_Cmp_Ge;
-                                                       *pnc_out = ia32_pn_Cmp_unsigned | pnc;
-                                                       return flags;
-                                               }
-                                       }
-                               }
+       /* check for bit-test */
+       if (ia32_cg_config.use_bt
+                       && (pnc == pn_Cmp_Lg || pnc == pn_Cmp_Eq || pnc == pn_Cmp_Ne
+                               || pnc == pn_Cmp_Ue)) {
+               ir_node *l = get_Cmp_left(cmp);
+               ir_node *r = get_Cmp_right(cmp);
+               if (is_And(l)) {
+                       ir_node *la = get_And_left(l);
+                       ir_node *ra = get_And_right(l);
+                       if (is_Shl(ra)) {
+                               ir_node *tmp = la;
+                               la = ra;
+                               ra = tmp;
                        }
-                       /* add ia32 compare flags */
-                       {
-                               ir_node *l    = get_Cmp_left(pred);
-                               ir_mode *mode = get_irn_mode(l);
-                               if (mode_is_float(mode))
-                                       pnc |= ia32_pn_Cmp_float;
-                               else if (! mode_is_signed(mode))
-                                       pnc |= ia32_pn_Cmp_unsigned;
+                       if (is_Shl(la)) {
+                               ir_node *c = get_Shl_left(la);
+                               if (is_Const_1(c) && is_Const_0(r)) {
+                                       /* (1 << n) & ra) */
+                                       ir_node *n = get_Shl_right(la);
+                                       flags    = gen_bt(cmp, ra, n);
+                                       /* the bit is copied into the CF flag */
+                                       if (pnc & pn_Cmp_Eq)
+                                               *cc_out = ia32_cc_below; /* ==0, so we test for CF=1 */
+                                       else
+                                               *cc_out = ia32_cc_above_equal; /* test for CF=0 */
+                                       return flags;
+                               }
                        }
-                       *pnc_out = pnc;
-                       flags = be_transform_node(pred);
-                       return flags;
                }
        }
 
-       /* a mode_b value, we have to compare it against 0 */
-       dbgi      = get_irn_dbg_info(node);
-       new_block = be_transform_node(get_nodes_block(node));
-       new_op    = be_transform_node(node);
-       flags     = new_bd_ia32_Test(dbgi, new_block, noreg_GP, noreg_GP, nomem, new_op,
-                                    new_op, /*is_permuted=*/0, /*cmp_unsigned=*/0);
-       *pnc_out  = pn_Cmp_Lg;
+       /* just do a normal transformation of the Cmp */
+       *cc_out = pnc_to_condition_code(pnc, mode);
+       flags   = be_transform_node(cmp);
        return flags;
 }
 
+/**
+ * Transform a node returning a "flag" result.
+ *
+ * @param node    the node to transform
+ * @param cc_out  the compare mode to use
+ */
+static ir_node *get_flags_node(ir_node *node, ia32_condition_code_t *cc_out)
+{
+       if (is_Proj(node) && is_Cmp(get_Proj_pred(node)))
+               return get_flags_node_cmp(node, cc_out);
+       assert(get_irn_mode(node) == mode_b);
+       return get_flags_mode_b(node, cc_out);
+}
+
 /**
  * Transforms a Load.
  *
@@ -2188,26 +2258,20 @@ static ir_node *dest_am_unop(ir_node *node, ir_node *op, ir_node *mem,
        return new_node;
 }
 
-static int ia32_get_negated_pnc(int pnc)
-{
-       ir_mode *mode = pnc & ia32_pn_Cmp_float ? mode_F : mode_Iu;
-       return get_negated_pnc(pnc, mode);
-}
-
 static ir_node *try_create_SetMem(ir_node *node, ir_node *ptr, ir_node *mem)
 {
-       ir_mode        *mode      = get_irn_mode(node);
-       ir_node        *mux_true  = get_Mux_true(node);
-       ir_node        *mux_false = get_Mux_false(node);
-       ir_node        *cond;
-       dbg_info       *dbgi;
-       ir_node        *block;
-       ir_node        *new_block;
-       ir_node        *flags;
-       ir_node        *new_node;
-       bool            negated;
-       int             pnc;
-       ia32_address_t  addr;
+       ir_mode              *mode      = get_irn_mode(node);
+       ir_node              *mux_true  = get_Mux_true(node);
+       ir_node              *mux_false = get_Mux_false(node);
+       ir_node              *cond;
+       dbg_info             *dbgi;
+       ir_node              *block;
+       ir_node              *new_block;
+       ir_node              *flags;
+       ir_node              *new_node;
+       bool                  negated;
+       ia32_condition_code_t cc;
+       ia32_address_t        addr;
 
        if (get_mode_size_bits(mode) != 8)
                return NULL;
@@ -2221,12 +2285,12 @@ static ir_node *try_create_SetMem(ir_node *node, ir_node *ptr, ir_node *mem)
        }
 
        cond  = get_Mux_sel(node);
-       flags = get_flags_node(cond, &pnc);
+       flags = get_flags_node(cond, &cc);
        /* we can't handle the float special cases with SetM */
-       if (pnc & ia32_pn_Cmp_float)
+       if (cc & ia32_cc_additional_float_cases)
                return NULL;
        if (negated)
-               pnc = ia32_get_negated_pnc(pnc);
+               cc = ia32_negate_condition_code(cc);
 
        build_address_ptr(&addr, ptr, mem);
 
@@ -2234,7 +2298,7 @@ static ir_node *try_create_SetMem(ir_node *node, ir_node *ptr, ir_node *mem)
        block     = get_nodes_block(node);
        new_block = be_transform_node(block);
        new_node  = new_bd_ia32_SetccMem(dbgi, new_block, addr.base,
-                                        addr.index, addr.mem, flags, pnc);
+                                        addr.index, addr.mem, flags, cc);
        set_address(new_node, &addr);
        set_ia32_op_type(new_node, ia32_AddrModeD);
        set_ia32_ls_mode(new_node, mode);
@@ -2674,23 +2738,23 @@ static ir_node *create_Switch(ir_node *node)
  */
 static ir_node *gen_Cond(ir_node *node)
 {
-       ir_node  *block     = get_nodes_block(node);
-       ir_node  *new_block = be_transform_node(block);
-       dbg_info *dbgi      = get_irn_dbg_info(node);
-       ir_node  *sel       = get_Cond_selector(node);
-       ir_mode  *sel_mode  = get_irn_mode(sel);
-       ir_node  *flags     = NULL;
-       ir_node  *new_node;
-       int       pnc;
+       ir_node              *block     = get_nodes_block(node);
+       ir_node              *new_block = be_transform_node(block);
+       dbg_info             *dbgi      = get_irn_dbg_info(node);
+       ir_node              *sel       = get_Cond_selector(node);
+       ir_mode              *sel_mode  = get_irn_mode(sel);
+       ir_node              *flags     = NULL;
+       ir_node              *new_node;
+       ia32_condition_code_t cc;
 
        if (sel_mode != mode_b) {
                return create_Switch(node);
        }
 
        /* we get flags from a Cmp */
-       flags = get_flags_node(sel, &pnc);
+       flags = get_flags_node(sel, &cc);
 
-       new_node = new_bd_ia32_Jcc(dbgi, new_block, flags, pnc);
+       new_node = new_bd_ia32_Jcc(dbgi, new_block, flags, cc);
        SET_IA32_ORIG_NODE(new_node, node);
 
        return new_node;
@@ -2886,7 +2950,6 @@ static ir_node *gen_Cmp(ir_node *node)
        ir_node  *new_node;
        ia32_address_mode_t  am;
        ia32_address_t      *addr = &am.addr;
-       int                  cmp_unsigned;
 
        if (mode_is_float(cmp_mode)) {
                if (ia32_cg_config.use_sse2) {
@@ -2899,7 +2962,6 @@ static ir_node *gen_Cmp(ir_node *node)
        assert(ia32_mode_needs_gp_reg(cmp_mode));
 
        /* Prefer the Test instruction, when encountering (x & y) ==/!= 0 */
-       cmp_unsigned = !mode_is_signed(cmp_mode);
        if (is_Const_0(right)          &&
            is_And(left)               &&
            get_irn_n_edges(left) == 1 &&
@@ -2927,11 +2989,10 @@ static ir_node *gen_Cmp(ir_node *node)
 
                if (get_mode_size_bits(cmp_mode) == 8) {
                        new_node = new_bd_ia32_Test8Bit(dbgi, new_block, addr->base,
-                                       addr->index, addr->mem, am.new_op1, am.new_op2, am.ins_permuted,
-                                       cmp_unsigned);
+                                       addr->index, addr->mem, am.new_op1, am.new_op2, am.ins_permuted);
                } else {
                        new_node = new_bd_ia32_Test(dbgi, new_block, addr->base, addr->index,
-                                       addr->mem, am.new_op1, am.new_op2, am.ins_permuted, cmp_unsigned);
+                                       addr->mem, am.new_op1, am.new_op2, am.ins_permuted);
                }
        } else {
                /* Cmp(left, right) */
@@ -2948,11 +3009,10 @@ static ir_node *gen_Cmp(ir_node *node)
                if (get_mode_size_bits(cmp_mode) == 8) {
                        new_node = new_bd_ia32_Cmp8Bit(dbgi, new_block, addr->base,
                                                       addr->index, addr->mem, am.new_op1,
-                                                      am.new_op2, am.ins_permuted,
-                                                      cmp_unsigned);
+                                                      am.new_op2, am.ins_permuted);
                } else {
                        new_node = new_bd_ia32_Cmp(dbgi, new_block, addr->base, addr->index,
-                                       addr->mem, am.new_op1, am.new_op2, am.ins_permuted, cmp_unsigned);
+                                       addr->mem, am.new_op1, am.new_op2, am.ins_permuted);
                }
        }
        set_am_attributes(new_node, &am);
@@ -2966,7 +3026,7 @@ static ir_node *gen_Cmp(ir_node *node)
 }
 
 static ir_node *create_CMov(ir_node *node, ir_node *flags, ir_node *new_flags,
-                            int pnc)
+                            ia32_condition_code_t cc)
 {
        dbg_info            *dbgi          = get_irn_dbg_info(node);
        ir_node             *block         = get_nodes_block(node);
@@ -2986,11 +3046,11 @@ static ir_node *create_CMov(ir_node *node, ir_node *flags, ir_node *new_flags,
                        match_commutative | match_am | match_16bit_am | match_mode_neutral);
 
        if (am.ins_permuted)
-               pnc = ia32_get_negated_pnc(pnc);
+               cc = ia32_invert_condition_code(cc);
 
        new_node = new_bd_ia32_CMovcc(dbgi, new_block, addr->base, addr->index,
                                      addr->mem, am.new_op1, am.new_op2, new_flags,
-                                     pnc);
+                                     cc);
        set_am_attributes(new_node, &am);
 
        SET_IA32_ORIG_NODE(new_node, node);
@@ -3004,13 +3064,13 @@ static ir_node *create_CMov(ir_node *node, ir_node *flags, ir_node *new_flags,
  * Creates a ia32 Setcc instruction.
  */
 static ir_node *create_set_32bit(dbg_info *dbgi, ir_node *new_block,
-                                 ir_node *flags, int pnc,
+                                 ir_node *flags, ia32_condition_code_t cc,
                                  ir_node *orig_node)
 {
        ir_mode *mode  = get_irn_mode(orig_node);
        ir_node *new_node;
 
-       new_node = new_bd_ia32_Setcc(dbgi, new_block, flags, pnc);
+       new_node = new_bd_ia32_Setcc(dbgi, new_block, flags, cc);
        SET_IA32_ORIG_NODE(new_node, orig_node);
 
        /* we might need to conv the result up */
@@ -3138,8 +3198,8 @@ enum setcc_transform_insn {
 };
 
 typedef struct setcc_transform {
-       unsigned num_steps;
-       int      pnc;
+       unsigned              num_steps;
+       ia32_condition_code_t cc;
        struct {
                enum setcc_transform_insn  transform;
                long val;
@@ -3152,7 +3212,8 @@ typedef struct setcc_transform {
  * Find a transformation that creates 0 and 1 from
  * tv_t and tv_f.
  */
-static void find_const_transform(int pnc, ir_tarval *t, ir_tarval *f,
+static void find_const_transform(ia32_condition_code_t cc,
+                                 ir_tarval *t, ir_tarval *f,
                                  setcc_transform_t *res)
 {
        unsigned step = 0;
@@ -3163,15 +3224,15 @@ static void find_const_transform(int pnc, ir_tarval *t, ir_tarval *f,
                ir_tarval *tmp = t;
                t = f;
                f = tmp;
-               pnc = ia32_get_negated_pnc(pnc);
+               cc = ia32_negate_condition_code(cc);
        } else if (tarval_cmp(t, f) == pn_Cmp_Lt) {
                // now, t is the bigger one
                ir_tarval *tmp = t;
                t = f;
                f = tmp;
-               pnc = ia32_get_negated_pnc(pnc);
+               cc = ia32_negate_condition_code(cc);
        }
-       res->pnc = pnc;
+       res->cc = cc;
 
        if (! tarval_is_null(f)) {
                ir_tarval *t_sub = tarval_sub(t, f, NULL);
@@ -3276,17 +3337,17 @@ static void find_const_transform(int pnc, ir_tarval *t, ir_tarval *f,
  */
 static ir_node *gen_Mux(ir_node *node)
 {
-       dbg_info *dbgi      = get_irn_dbg_info(node);
-       ir_node  *block     = get_nodes_block(node);
-       ir_node  *new_block = be_transform_node(block);
-       ir_node  *mux_true  = get_Mux_true(node);
-       ir_node  *mux_false = get_Mux_false(node);
-       ir_node  *cond      = get_Mux_sel(node);
-       ir_mode  *mode      = get_irn_mode(node);
-       ir_node  *flags;
-       ir_node  *new_node;
-       int       is_abs;
-       int       pnc;
+       dbg_info             *dbgi      = get_irn_dbg_info(node);
+       ir_node              *block     = get_nodes_block(node);
+       ir_node              *new_block = be_transform_node(block);
+       ir_node              *mux_true  = get_Mux_true(node);
+       ir_node              *mux_false = get_Mux_false(node);
+       ir_node              *cond      = get_Mux_sel(node);
+       ir_mode              *mode      = get_irn_mode(node);
+       ir_node              *flags;
+       ir_node              *new_node;
+       int                   is_abs;
+       ia32_condition_code_t cc;
 
        assert(get_irn_mode(cond) == mode_b);
 
@@ -3332,8 +3393,8 @@ static ir_node *gen_Mux(ir_node *node)
                        ir_mode             *new_mode;
                        unsigned            scale;
 
-                       flags    = get_flags_node(cond, &pnc);
-                       new_node = create_set_32bit(dbgi, new_block, flags, pnc, node);
+                       flags    = get_flags_node(cond, &cc);
+                       new_node = create_set_32bit(dbgi, new_block, flags, cc, node);
 
                        if (ia32_cg_config.use_sse2) {
                                /* cannot load from different mode on SSE */
@@ -3388,7 +3449,7 @@ static ir_node *gen_Mux(ir_node *node)
                        am.new_op2            = NULL;
                        am.pinned             = op_pin_state_floats;
                        am.commutative        = 1;
-                       am.ins_permuted       = 0;
+                       am.ins_permuted       = false;
 
                        if (ia32_cg_config.use_sse2)
                                load = new_bd_ia32_xLoad(dbgi, block, am.addr.base, am.addr.index, am.addr.mem, new_mode);
@@ -3416,7 +3477,7 @@ static ir_node *gen_Mux(ir_node *node)
                                        ir_node *tmp = val_false;
                                        val_false = val_true;
                                        val_true  = tmp;
-                                       pnc       = ia32_get_negated_pnc(pnc);
+                                       pnc       = get_negated_pnc(pnc, get_irn_mode(cmp_left));
                                }
                                if (is_Const_0(val_false) && is_Sub(val_true)) {
                                        if ((pnc == pn_Cmp_Gt || pnc == pn_Cmp_Ge)
@@ -3433,7 +3494,7 @@ static ir_node *gen_Mux(ir_node *node)
                        }
                }
 
-               flags = get_flags_node(cond, &pnc);
+               flags = get_flags_node(cond, &cc);
 
                if (is_Const(mux_true) && is_Const(mux_false)) {
                        /* both are const, good */
@@ -3442,7 +3503,7 @@ static ir_node *gen_Mux(ir_node *node)
                        setcc_transform_t res;
                        int step;
 
-                       find_const_transform(pnc, tv_true, tv_false, &res);
+                       find_const_transform(cc, tv_true, tv_false, &res);
                        new_node = node;
                        for (step = (int)res.num_steps - 1; step >= 0; --step) {
                                ir_node *imm;
@@ -3480,7 +3541,7 @@ static ir_node *gen_Mux(ir_node *node)
                                        new_node = new_bd_ia32_And(dbgi, new_block, noreg_GP, noreg_GP, nomem, new_node, imm);
                                        break;
                                case SETCC_TR_SET:
-                                       new_node = create_set_32bit(dbgi, new_block, flags, res.pnc, node);
+                                       new_node = create_set_32bit(dbgi, new_block, flags, res.cc, node);
                                        break;
                                case SETCC_TR_SBB:
                                        new_node = new_bd_ia32_Sbb0(dbgi, new_block, flags);
@@ -3490,7 +3551,7 @@ static ir_node *gen_Mux(ir_node *node)
                                }
                        }
                } else {
-                       new_node = create_CMov(node, cond, flags, pnc);
+                       new_node = create_CMov(node, cond, flags, cc);
                }
                return new_node;
        }
@@ -4085,41 +4146,6 @@ static ir_node *gen_IJmp(ir_node *node)
        return new_node;
 }
 
-/**
- * Transform a Bound node.
- */
-static ir_node *gen_Bound(ir_node *node)
-{
-       ir_node  *new_node;
-       ir_node  *lower = get_Bound_lower(node);
-       dbg_info *dbgi  = get_irn_dbg_info(node);
-
-       if (is_Const_0(lower)) {
-               /* typical case for Java */
-               ir_node  *sub, *res, *flags, *block;
-
-               res = gen_binop(node, get_Bound_index(node), get_Bound_upper(node),
-                               new_bd_ia32_Sub,
-                               match_mode_neutral | match_am | match_immediate);
-
-               block = get_nodes_block(res);
-               if (! is_Proj(res)) {
-                       sub = res;
-                       set_irn_mode(sub, mode_T);
-                       res = new_rd_Proj(NULL, sub, mode_Iu, pn_ia32_res);
-               } else {
-                       sub = get_Proj_pred(res);
-               }
-               flags = new_rd_Proj(NULL, sub, mode_Iu, pn_ia32_Sub_flags);
-               new_node = new_bd_ia32_Jcc(dbgi, block, flags, pn_Cmp_Lt | ia32_pn_Cmp_unsigned);
-               SET_IA32_ORIG_NODE(new_node, node);
-       } else {
-               panic("generic Bound not supported in ia32 Backend");
-       }
-       return new_node;
-}
-
-
 static ir_node *gen_ia32_l_ShlDep(ir_node *node)
 {
        ir_node *left  = get_irn_n(node, n_ia32_l_ShlDep_val);
@@ -4349,7 +4375,7 @@ static ir_node *gen_ia32_l_LLtoFloat(ir_node *node)
                am.new_op2            = ia32_new_NoReg_vfp(current_ir_graph);
                am.pinned             = op_pin_state_floats;
                am.commutative        = 1;
-               am.ins_permuted       = 0;
+               am.ins_permuted       = false;
 
                fadd  = new_bd_ia32_vfadd(dbgi, block, am.addr.base, am.addr.index, am.addr.mem,
                        am.new_op1, am.new_op2, get_fpcw());
@@ -5051,7 +5077,7 @@ static ir_node *gen_parity(ir_node *node)
        match_arguments(&am, block, NULL, param, NULL, match_am);
        imm = ia32_create_Immediate(NULL, 0, 0);
        cmp = new_bd_ia32_Cmp(dbgi, new_block, addr->base, addr->index,
-                             addr->mem, imm, am.new_op2, am.ins_permuted, 0);
+                             addr->mem, imm, am.new_op2, am.ins_permuted);
        set_am_attributes(cmp, &am);
        set_ia32_ls_mode(cmp, mode_Iu);
 
@@ -5060,7 +5086,7 @@ static ir_node *gen_parity(ir_node *node)
        cmp = fix_mem_proj(cmp, &am);
 
        /* setp */
-       new_node = new_bd_ia32_Setcc(dbgi, new_block, cmp, ia32_pn_Cmp_parity);
+       new_node = new_bd_ia32_Setcc(dbgi, new_block, cmp, ia32_cc_parity);
        SET_IA32_ORIG_NODE(new_node, node);
 
        /* conv to 32bit */
@@ -5510,30 +5536,6 @@ static ir_node *gen_Proj_Cmp(ir_node *node)
              node);
 }
 
-/**
- * Transform the Projs from a Bound.
- */
-static ir_node *gen_Proj_Bound(ir_node *node)
-{
-       ir_node *new_node;
-       ir_node *pred = get_Proj_pred(node);
-
-       switch (get_Proj_proj(node)) {
-       case pn_Bound_M:
-               return be_transform_node(get_Bound_mem(pred));
-       case pn_Bound_X_regular:
-               new_node = be_transform_node(pred);
-               return new_r_Proj(new_node, mode_X, pn_ia32_Jcc_true);
-       case pn_Bound_X_except:
-               new_node = be_transform_node(pred);
-               return new_r_Proj(new_node, mode_X, pn_ia32_Jcc_false);
-       case pn_Bound_res:
-               return be_transform_node(get_Bound_index(pred));
-       default:
-               panic("unsupported Proj from Bound");
-       }
-}
-
 static ir_node *gen_Proj_ASM(ir_node *node)
 {
        ir_mode *mode     = get_irn_mode(node);
@@ -5590,8 +5592,6 @@ static ir_node *gen_Proj(ir_node *node)
                return gen_Proj_be_Call(node);
        case iro_Cmp:
                return gen_Proj_Cmp(node);
-       case iro_Bound:
-               return gen_Proj_Bound(node);
        case iro_Start:
                proj = get_Proj_proj(node);
                switch (proj) {
@@ -5649,7 +5649,6 @@ static void register_transformers(void)
        be_set_transform_function(op_be_IncSP,         gen_be_IncSP);
        be_set_transform_function(op_be_Return,        gen_be_Return);
        be_set_transform_function(op_be_SubSP,         gen_be_SubSP);
-       be_set_transform_function(op_Bound,            gen_Bound);
        be_set_transform_function(op_Builtin,          gen_Builtin);
        be_set_transform_function(op_Cmp,              gen_Cmp);
        be_set_transform_function(op_Cond,             gen_Cond);