backend_marked was a buggy/wrong concept, removed it
[libfirm] / ir / be / ia32 / ia32_emitter.c
index 6235db6..4716f55 100644 (file)
@@ -282,11 +282,10 @@ void ia32_emit_source_register(const ir_node *node, int pos)
 
 static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust)
 {
-       set_entity_backend_marked(entity, 1);
        be_gas_emit_entity(entity);
 
        if (get_entity_owner(entity) == get_tls_type()) {
-               if (get_entity_visibility(entity) == visibility_external_allocated) {
+               if (get_entity_linkage(entity) & IR_LINKAGE_EXTERN) {
                        be_emit_cstring("@INDNTPOFF");
                } else {
                        be_emit_cstring("@NTPOFF");
@@ -556,6 +555,7 @@ static void ia32_emit_cmp_suffix(int pnc)
                be_emit_char('p');
                return;
        }
+
        if (pnc & ia32_pn_Cmp_float || pnc & ia32_pn_Cmp_unsigned) {
                str = cmp2condition_u[pnc & 7];
        } else {
@@ -568,7 +568,9 @@ static void ia32_emit_cmp_suffix(int pnc)
 typedef enum ia32_emit_mod_t {
        EMIT_RESPECT_LS   = 1U << 0,
        EMIT_ALTERNATE_AM = 1U << 1,
-       EMIT_LONG         = 1U << 2
+       EMIT_LONG         = 1U << 2,
+       EMIT_HIGH_REG     = 1U << 3,
+       EMIT_LOW_REG      = 1U << 4
 } ia32_emit_mod_t;
 
 /**
@@ -647,9 +649,11 @@ void ia32_emit_am(const ir_node *node)
  * %d   signed int              signed int
  *
  * x starts at 0
- * # modifier for %ASx, %D and %S uses ls mode of node to alter register width
+ * # modifier for %ASx, %D, %R, and %S uses ls mode of node to alter register width
  * * modifier does not prefix immediates with $, but AM with *
  * l modifier for %lu and %ld
+ * > modifier to output high 8bit register (ah, bh)
+ * < modifier to output low 8bit register (al, bl)
  */
 static void ia32_emitf(const ir_node *node, const char *fmt, ...)
 {
@@ -678,20 +682,19 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...)
                        break;
 
                ++fmt;
-               if (*fmt == '*') {
-                       mod |= EMIT_ALTERNATE_AM;
-                       ++fmt;
-               }
-
-               if (*fmt == '#') {
-                       mod |= EMIT_RESPECT_LS;
-                       ++fmt;
-               }
-
-               if (*fmt == 'l') {
-                       mod |= EMIT_LONG;
+               while (1) {
+                       switch(*fmt) {
+                       case '*': mod |= EMIT_ALTERNATE_AM; break;
+                       case '#': mod |= EMIT_RESPECT_LS;   break;
+                       case 'l': mod |= EMIT_LONG;         break;
+                       case '>': mod |= EMIT_HIGH_REG;     break;
+                       case '<': mod |= EMIT_LOW_REG;      break;
+                       default:
+                               goto end_of_mods;
+                       }
                        ++fmt;
                }
+end_of_mods:
 
                switch (*fmt++) {
                        case '%':
@@ -700,20 +703,20 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...)
 
                        case 'A': {
                                switch (*fmt++) {
+emit_AM:
                                        case 'M':
                                                if (mod & EMIT_ALTERNATE_AM)
                                                        be_emit_char('*');
-
                                                ia32_emit_am(node);
                                                break;
 
                                        case 'R': {
                                                const arch_register_t *reg = va_arg(ap, const arch_register_t*);
-                                               if (mod & EMIT_ALTERNATE_AM)
-                                                       be_emit_char('*');
                                                if (get_ia32_op_type(node) == ia32_AddrModeS) {
-                                                       ia32_emit_am(node);
+                                                       goto emit_AM;
                                                } else {
+                                                       if (mod & EMIT_ALTERNATE_AM)
+                                                               be_emit_char('*');
                                                        emit_register(reg, NULL);
                                                }
                                                break;
@@ -721,10 +724,8 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...)
 
                                        case 'S':
                                                if (get_ia32_op_type(node) == ia32_AddrModeS) {
-                                                       if (mod & EMIT_ALTERNATE_AM)
-                                                               be_emit_char('*');
-                                                       ia32_emit_am(node);
                                                        ++fmt;
+                                                       goto emit_AM;
                                                } else {
                                                        assert(get_ia32_op_type(node) == ia32_Normal);
                                                        goto emit_S;
@@ -772,7 +773,13 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...)
 
                        case 'R': {
                                const arch_register_t *reg = va_arg(ap, const arch_register_t*);
-                               emit_register(reg, NULL);
+                               if (mod & EMIT_HIGH_REG) {
+                                       emit_8bit_register_high(reg);
+                               } else if (mod & EMIT_LOW_REG) {
+                                       emit_8bit_register(reg);
+                               } else {
+                                       emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL);
+                               }
                                break;
                        }
 
@@ -949,8 +956,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_pnc(const ir_node *node, int flags_pos, int pnc)
 {
        ir_node           *flags = get_irn_n(node, flags_pos);
        const ia32_attr_t *flags_attr;
@@ -1083,37 +1089,37 @@ static void emit_ia32_Jcc(const ir_node *node)
        if (pnc & ia32_pn_Cmp_float) {
                /* 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: {
-                               ia32_emitf(proj_true, "\tjp %L\n");
-                               break;
-                       }
+               switch (pnc & 0x0f) {
+               case pn_Cmp_Uo: {
+                       ia32_emitf(proj_true, "\tjp %L\n");
+                       break;
+               }
 
-                       case pn_Cmp_Leg:
-                               ia32_emitf(proj_true, "\tjnp %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:
-                               /* 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)) {
-                                       need_parity_label = 1;
-                                       ia32_emitf(proj_false, "\tjp 1f\n");
-                               } else {
-                                       ia32_emitf(proj_false, "\tjp %L\n");
-                               }
-                               goto emit_jcc;
+               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)) {
+                               need_parity_label = 1;
+                               ia32_emitf(proj_false, "\tjp 1f\n");
+                       } 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;
+               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;
+               default:
+                       goto emit_jcc;
                }
        } else {
 emit_jcc:
@@ -1132,19 +1138,65 @@ emit_jcc:
        }
 }
 
-static void emit_ia32_CMov(const ir_node *node)
+/**
+ * Emits an ia32 Setcc. This is mostly easy but some floating point compares
+ * are tricky.
+ */
+static void emit_ia32_Setcc(const ir_node *node)
+{
+       const arch_register_t *dreg = get_out_reg(node, pn_ia32_Setcc_res);
+
+       pn_Cmp 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_emitf(node, "\tsetp %>R\n", dreg);
+                       ia32_emitf(node, "\torb %>R, %<R\n", dreg, dreg);
+                       return;
+
+               default:
+                       break;
+               }
+       }
+       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);
-       int                    ins_permuted = attr->data.ins_permuted;
        const arch_register_t *out          = arch_irn_get_register(node, pn_ia32_res);
        pn_Cmp                 pnc          = get_ia32_condcode(node);
        const arch_register_t *in_true;
        const arch_register_t *in_false;
 
-       pnc = determine_final_pnc(node, n_ia32_CMov_eflags, pnc);
+       pnc = determine_final_pnc(node, n_ia32_CMovcc_eflags, pnc);
+       /* although you can't set ins_permuted in the constructor it might still
+          be set by memory operand folding */
+       if (attr->data.ins_permuted)
+               pnc = ia32_get_negated_pnc(pnc);
 
-       in_true  = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_true));
-       in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_false));
+       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));
 
        /* should be same constraint fullfilled? */
        if (out == in_false) {
@@ -1154,7 +1206,7 @@ static void emit_ia32_CMov(const ir_node *node)
 
                assert(get_ia32_op_type(node) == ia32_Normal);
 
-               ins_permuted = !ins_permuted;
+               pnc = ia32_get_negated_pnc(pnc);
 
                tmp      = in_true;
                in_true  = in_false;
@@ -1164,10 +1216,20 @@ static void emit_ia32_CMov(const ir_node *node)
                ia32_emitf(node, "\tmovl %R, %R\n", in_false, out);
        }
 
-       if (ins_permuted)
-               pnc = ia32_get_negated_pnc(pnc);
-
        /* 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");
+               }
+       }
 
        ia32_emitf(node, "\tcmov%P %#AR, %#R\n", pnc, in_true, out);
 }
@@ -1226,8 +1288,8 @@ static void generate_jump_table(jmp_tbl_t *tbl, const ir_node *node)
        tbl->defProj      = NULL;
        tbl->num_branches = get_irn_n_edges(node) - 1;
        tbl->branches     = XMALLOCNZ(branch_t, tbl->num_branches);
-       tbl->min_value    = INT_MAX;
-       tbl->max_value    = INT_MIN;
+       tbl->min_value    = LONG_MAX;
+       tbl->max_value    = LONG_MIN;
 
        default_pn = get_ia32_condcode(node);
        i = 0;
@@ -1871,7 +1933,7 @@ static void ia32_register_emitters(void)
        /* other ia32 emitter functions */
        IA32_EMIT2(Conv_I2I8Bit, Conv_I2I);
        IA32_EMIT(Asm);
-       IA32_EMIT(CMov);
+       IA32_EMIT(CMovcc);
        IA32_EMIT(Call);
        IA32_EMIT(Const);
        IA32_EMIT(Conv_FP2FP);
@@ -1883,6 +1945,7 @@ static void ia32_register_emitters(void)
        IA32_EMIT(GetEIP);
        IA32_EMIT(IMul);
        IA32_EMIT(Jcc);
+       IA32_EMIT(Setcc);
        IA32_EMIT(LdTls);
        IA32_EMIT(Minus64Bit);
        IA32_EMIT(SwitchJmp);
@@ -2180,6 +2243,8 @@ void ia32_gen_routine(ia32_code_gen_t *ia32_cg, ir_graph *irg)
        isa      = cg->isa;
        do_pic   = cg->birg->main_env->options->pic;
 
+       be_gas_elf_type_char = '@';
+
        ia32_register_emitters();
 
        get_unique_label(pic_base_label, sizeof(pic_base_label), ".PIC_BASE");
@@ -2270,6 +2335,7 @@ static void build_reg_map(void)
        pnc_map_unsigned[pn_Cmp_Lg]    = 0x05;
 }
 
+/** Returns the encoding for a pnc field. */
 static unsigned char pnc2cc(int pnc)
 {
        unsigned char cc;
@@ -2348,11 +2414,10 @@ static void bemit_entity(ir_entity *entity, bool entity_sign, int offset,
        be_emit_cstring("\t.long ");
        if (entity_sign)
                be_emit_char('-');
-       set_entity_backend_marked(entity, 1);
        be_gas_emit_entity(entity);
 
        if (get_entity_owner(entity) == get_tls_type()) {
-               if (get_entity_visibility(entity) == visibility_external_allocated) {
+               if (get_entity_linkage(entity) & IR_LINKAGE_EXTERN) {
                        be_emit_cstring("@INDNTPOFF");
                } else {
                        be_emit_cstring("@NTPOFF");
@@ -2382,6 +2447,11 @@ static void bemit_jmp_destination(const ir_node *dest_block)
 /* end emit routines, all emitters following here should only use the functions
    above. */
 
+typedef enum reg_modifier {
+       REG_LOW  = 0,
+       REG_HIGH = 1
+} reg_modifier_t;
+
 /** Create a ModR/M byte for src1,src2 registers */
 static void bemit_modrr(const arch_register_t *src1,
                         const arch_register_t *src2)
@@ -2392,6 +2462,16 @@ static void bemit_modrr(const arch_register_t *src1,
        bemit8(modrm);
 }
 
+/** Create a ModR/M8 byte for src1,src2 registers */
+static void bemit_modrr8(reg_modifier_t high_part1, const arch_register_t *src1,
+                                                reg_modifier_t high_part2, const arch_register_t *src2)
+{
+       unsigned char modrm = MOD_REG;
+       modrm |= ENC_RM(reg_gp_map[src1->index] +  (high_part1 == REG_HIGH ? 4 : 0));
+       modrm |= ENC_REG(reg_gp_map[src2->index] + (high_part2 == REG_HIGH ? 4 : 0));
+       bemit8(modrm);
+}
+
 /** Create a ModR/M byte for one register and extension */
 static void bemit_modru(const arch_register_t *reg, unsigned ext)
 {
@@ -2402,6 +2482,16 @@ static void bemit_modru(const arch_register_t *reg, unsigned ext)
        bemit8(modrm);
 }
 
+/** Create a ModR/M8 byte for one register */
+static void bemit_modrm8(reg_modifier_t high_part, const arch_register_t *reg)
+{
+       unsigned char modrm = MOD_REG;
+       assert(reg_gp_map[reg->index] < 4);
+       modrm |= ENC_RM(reg_gp_map[reg->index] + (high_part == REG_HIGH ? 4 : 0));
+       modrm |= MOD_REG;
+       bemit8(modrm);
+}
+
 /**
  * Calculate the size of an signed immediate in bytes.
  *
@@ -2715,10 +2805,11 @@ BINOP(test, 0x85, 0xA9, 0xF7, 0)
 #define BINOPMEM(op, ext) \
 static void bemit_##op(const ir_node *node) \
 { \
+       ir_node *val; \
        unsigned size = get_mode_size_bits(get_ia32_ls_mode(node)); \
        if (size == 16) \
                bemit8(0x66); \
-       ir_node *val = get_irn_n(node, n_ia32_unary_op); \
+       val = get_irn_n(node, n_ia32_unary_op); \
        if (is_ia32_Immediate(val)) { \
                const ia32_immediate_attr_t *attr   = get_ia32_immediate_attr_const(val); \
                int                          offset = attr->offset; \
@@ -2802,10 +2893,11 @@ static void bemit_##op(const ir_node *node) \
  \
 static void bemit_##op##mem(const ir_node *node) \
 { \
+       ir_node *count; \
        unsigned size = get_mode_size_bits(get_ia32_ls_mode(node)); \
        if (size == 16) \
                bemit8(0x66); \
-       ir_node *count = get_irn_n(node, 1); \
+       count = get_irn_n(node, 1); \
        if (is_ia32_Immediate(count)) { \
                int offset = get_ia32_immediate_attr_const(count)->offset; \
                if (offset == 1) { \
@@ -2860,7 +2952,78 @@ static void bemit_shrd(const ir_node *node)
        }
 }
 
-static void bemit_cmov(const ir_node *node)
+/**
+ * binary emitter for setcc.
+ */
+static void bemit_setcc(const ir_node *node)
+{
+       const arch_register_t *dreg = get_out_reg(node, pn_ia32_Setcc_res);
+
+       pn_Cmp 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 */
+                       bemit8(0x0F);
+                       bemit8(0x9A);
+                       bemit_modrm8(REG_LOW, dreg);
+                       return;
+
+               case pn_Cmp_Leg:
+                        /* setnp <dreg*/
+                       bemit8(0x0F);
+                       bemit8(0x9B);
+                       bemit_modrm8(REG_LOW, dreg);
+                       return;
+
+               case pn_Cmp_Eq:
+               case pn_Cmp_Lt:
+               case pn_Cmp_Le:
+                        /* set%PNC <dreg */
+                       bemit8(0x0F);
+                       bemit8(0x90 | pnc2cc(pnc));
+                       bemit_modrm8(REG_LOW, dreg);
+
+                       /* setnp >dreg */
+                       bemit8(0x0F);
+                       bemit8(0x9B);
+                       bemit_modrm8(REG_HIGH, dreg);
+
+                       /* 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;
+               }
+       }
+       /* set%PNC <dreg */
+       bemit8(0x0F);
+       bemit8(0x90 | pnc2cc(pnc));
+       bemit_modrm8(REG_LOW, dreg);
+}
+
+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;
@@ -2869,10 +3032,10 @@ static void bemit_cmov(const ir_node *node)
        const arch_register_t *in_true;
        const arch_register_t *in_false;
 
-       pnc = determine_final_pnc(node, n_ia32_CMov_eflags, pnc);
+       pnc = determine_final_pnc(node, n_ia32_CMovcc_eflags, pnc);
 
-       in_true  = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_true));
-       in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_false));
+       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));
 
        /* should be same constraint fullfilled? */
        if (out == in_false) {
@@ -2893,7 +3056,7 @@ static void bemit_cmov(const ir_node *node)
        /* TODO: handling of Nans isn't correct yet */
 
        bemit8(0x0F);
-       bemit8(0x40 + pnc2cc(pnc));
+       bemit8(0x40 | pnc2cc(pnc));
        if (get_ia32_op_type(node) == ia32_Normal) {
                bemit_modrr(in_true, out);
        } else {
@@ -2988,8 +3151,8 @@ static void bemit_cmp8bit(const ir_node *node)
                }
                bemit8(get_ia32_immediate_attr_const(right)->offset);
        } else {
-               bemit8(0x3A);
                const arch_register_t *out = get_in_reg(node, n_ia32_Cmp_left);
+               bemit8(0x3A);
                if (get_ia32_op_type(node) == ia32_Normal) {
                        const arch_register_t *in = get_in_reg(node, n_ia32_Cmp_right);
                        bemit_modrr(out, in);
@@ -3017,8 +3180,8 @@ static void bemit_test8bit(const ir_node *node)
                }
                bemit8(get_ia32_immediate_attr_const(right)->offset);
        } else {
-               bemit8(0x84);
                const arch_register_t *out = get_in_reg(node, n_ia32_Test8Bit_left);
+               bemit8(0x84);
                if (get_ia32_op_type(node) == ia32_Normal) {
                        const arch_register_t *in = get_in_reg(node, n_ia32_Test8Bit_right);
                        bemit_modrr(out, in);
@@ -3070,21 +3233,6 @@ UNOPMEM(negmem, 0xF6, 3)
 UNOPMEM(incmem, 0xFE, 0)
 UNOPMEM(decmem, 0xFE, 1)
 
-static void bemit_set(const ir_node *node)
-{
-       pn_Cmp pnc;
-
-       bemit8(0x0F);
-
-       pnc = get_ia32_condcode(node);
-       pnc = determine_final_pnc(node, n_ia32_Set_eflags, pnc);
-       if (get_ia32_attr_const(node)->data.ins_permuted)
-               pnc = ia32_get_negated_pnc(pnc);
-
-       bemit8(0x90 + pnc2cc(pnc));
-       bemit_modru(get_out_reg(node, pn_ia32_Set_res), 2);
-}
-
 static void bemit_ldtls(const ir_node *node)
 {
        const arch_register_t *out = get_out_reg(node, 0);
@@ -4030,7 +4178,7 @@ static void ia32_register_binary_emitters(void)
        register_emitter(op_ia32_AndMem,        bemit_andmem);
        register_emitter(op_ia32_AndMem8Bit,    bemit_andmem8bit);
        register_emitter(op_ia32_Breakpoint,    bemit_int3);
-       register_emitter(op_ia32_CMov,          bemit_cmov);
+       register_emitter(op_ia32_CMovcc,        bemit_cmovcc);
        register_emitter(op_ia32_Call,          bemit_call);
        register_emitter(op_ia32_Cltd,          bemit_cltd);
        register_emitter(op_ia32_Cmc,           bemit_cmc);
@@ -4086,7 +4234,7 @@ static void ia32_register_binary_emitters(void)
        register_emitter(op_ia32_Sar,           bemit_sar);
        register_emitter(op_ia32_SarMem,        bemit_sarmem);
        register_emitter(op_ia32_Sbb,           bemit_sbb);
-       register_emitter(op_ia32_Set,           bemit_set);
+       register_emitter(op_ia32_Setcc,         bemit_setcc);
        register_emitter(op_ia32_Shl,           bemit_shl);
        register_emitter(op_ia32_ShlD,          bemit_shld);
        register_emitter(op_ia32_ShlMem,        bemit_shlmem);