fix sse/x87 fixup code added at wrong places
[libfirm] / ir / be / ia32 / ia32_emitter.c
index 801c05e..1ccd8a1 100644 (file)
@@ -250,6 +250,29 @@ void ia32_emit_source_register(ia32_emit_env_t *env, const ir_node *node, int po
        be_emit_string(env, reg_name);
 }
 
+void ia32_emit_8bit_source_register(ia32_emit_env_t *env, const ir_node *node, int pos)
+{
+       const arch_register_t *reg = get_in_reg(env, node, pos);
+       const char *reg_name = arch_register_get_name(reg);
+
+       assert(pos < get_irn_arity(node));
+
+       be_emit_char(env, '%');
+       be_emit_char(env, reg_name[1]);
+       be_emit_char(env, 'l');
+}
+
+void ia32_emit_16bit_source_register(ia32_emit_env_t *env, const ir_node *node, int pos)
+{
+       const arch_register_t *reg = get_in_reg(env, node, pos);
+       const char *reg_name = arch_register_get_name(reg);
+
+       assert(pos < get_irn_arity(node));
+
+       be_emit_char(env, '%');
+       be_emit_string(env, &reg_name[1]);
+}
+
 void ia32_emit_dest_register(ia32_emit_env_t *env, const ir_node *node, int pos) {
        const arch_register_t *reg = get_out_reg(env, node, pos);
        const char *reg_name = arch_register_get_name(reg);
@@ -639,6 +662,11 @@ void ia32_emit_am(ia32_emit_env_t *env, const ir_node *node) {
                }
                be_emit_char(env, ')');
        }
+
+       /* special case if nothing is set */
+       if(ent == NULL && offs == 0 && !has_base && !has_index) {
+               be_emit_char(env, '0');
+       }
 }
 
 /*************************************************
@@ -675,14 +703,6 @@ const struct cmp2conditon_t cmp2condition_s[] = {
        { "ge",              pn_Cmp_Ge },     /* >= */
        { "ne",              pn_Cmp_Lg },     /* != */
        { NULL,              pn_Cmp_Leg},     /* Floating point: ordered */
-       { NULL,              pn_Cmp_Uo },     /* Floating point: unordered */
-       { "e",               pn_Cmp_Ue },     /* Floating point: unordered or == */
-       { "b",               pn_Cmp_Ul },     /* Floating point: unordered or < */
-       { "be",              pn_Cmp_Ule },    /* Floating point: unordered or <= */
-       { "a",               pn_Cmp_Ug },     /* Floating point: unordered or > */
-       { "ae",              pn_Cmp_Uge },    /* Floating point: unordered or >= */
-       { "ne",              pn_Cmp_Ne },     /* Floating point: unordered or != */
-       { NULL,              pn_Cmp_True },   /* always true */
 };
 
 /*
@@ -706,13 +726,13 @@ const struct cmp2conditon_t cmp2condition_u[] = {
 static
 const char *get_cmp_suffix(pn_Cmp cmp_code)
 {
-       assert( (cmp2condition_s[cmp_code & 15].num) == (cmp_code & 15));
+       assert( (cmp2condition_s[cmp_code & 7].num) == (cmp_code & 7));
        assert( (cmp2condition_u[cmp_code & 7].num) == (cmp_code & 7));
 
        if((cmp_code & ia32_pn_Cmp_Unsigned)) {
                return cmp2condition_u[cmp_code & 7].name;
        } else {
-               return cmp2condition_s[cmp_code & 15].name;
+               return cmp2condition_s[cmp_code & 7].name;
        }
 }
 
@@ -736,8 +756,13 @@ ir_node *get_cfop_target_block(const ir_node *irn) {
 static
 void ia32_emit_block_name(ia32_emit_env_t *env, const ir_node *block)
 {
-       be_emit_cstring(env, BLOCK_PREFIX);
-       be_emit_irprintf(env->emit, "%d", get_irn_node_nr(block));
+       if (has_Block_label(block)) {
+               be_emit_string(env, be_gas_label_prefix());
+               be_emit_irprintf(env->emit, "%u", (unsigned)get_Block_label(block));
+       } else {
+               be_emit_cstring(env, BLOCK_PREFIX);
+               be_emit_irprintf(env->emit, "%d", get_irn_node_nr(block));
+       }
 }
 
 /**
@@ -813,19 +838,54 @@ void finish_CondJmp(ia32_emit_env_t *env, const ir_node *node, ir_mode *mode,
                pnc        = get_negated_pnc(pnc, mode);
        }
 
-       /* in case of unordered compare, check for parity */
-       if (pnc & pn_Cmp_Uo) {
-               be_emit_cstring(env, "\tjp ");
+       if (mode_is_float(mode)) {
+               /* Some floating point comparisons require a test of the parity flag, which
+                * indicates that the result is unordered */
+               switch (pnc) {
+                       case pn_Cmp_Uo:
+                               be_emit_cstring(env, "\tjp ");
+                               ia32_emit_cfop_target(env, proj_true);
+                               be_emit_finish_line_gas(env, proj_true);
+                               break;
+
+                       case pn_Cmp_Leg:
+                               be_emit_cstring(env, "\tjnp ");
+                               ia32_emit_cfop_target(env, proj_true);
+                               be_emit_finish_line_gas(env, proj_true);
+                               break;
+
+                       case pn_Cmp_Eq:
+                       case pn_Cmp_Lt:
+                       case pn_Cmp_Le:
+                               be_emit_cstring(env, "\tjp ");
+                               ia32_emit_cfop_target(env, proj_false);
+                               be_emit_finish_line_gas(env, proj_false);
+                               goto float_jcc;
+
+                       case pn_Cmp_Ug:
+                       case pn_Cmp_Uge:
+                       case pn_Cmp_Ne:
+                               be_emit_cstring(env, "\tjp ");
+                               ia32_emit_cfop_target(env, proj_true);
+                               be_emit_finish_line_gas(env, proj_true);
+                               goto float_jcc;
+
+                       default:
+                       float_jcc:
+                               /* The bits set by floating point compares correspond to unsigned
+                                * comparisons */
+                               pnc |= ia32_pn_Cmp_Unsigned;
+                               goto emit_jcc;
+               }
+       } else {
+emit_jcc:
+               be_emit_cstring(env, "\tj");
+               ia32_emit_cmp_suffix(env, pnc);
+               be_emit_char(env, ' ');
                ia32_emit_cfop_target(env, proj_true);
                be_emit_finish_line_gas(env, proj_true);
        }
 
-       be_emit_cstring(env, "\tj");
-       ia32_emit_cmp_suffix(env, pnc);
-       be_emit_char(env, ' ');
-       ia32_emit_cfop_target(env, proj_true);
-       be_emit_finish_line_gas(env, proj_true);
-
        /* the second Proj might be a fallthrough */
        if (get_cfop_target_block(proj_false) != next_block) {
                be_emit_cstring(env, "\tjmp ");
@@ -999,7 +1059,7 @@ void CMov_emitter(ia32_emit_env_t *env, const ir_node *node)
        }
 
        be_emit_cstring(env, "\tcmov");
-       ia32_emit_cmp_suffix(env, pnc);
+       ia32_emit_cmp_suffix(env, pnc );
        be_emit_cstring(env, "l ");
        ia32_emit_register(env, in1);
        be_emit_cstring(env, ", ");
@@ -1350,7 +1410,7 @@ void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node)
        if(attr->symconst == NULL || attr->offset != 0) {
                if(attr->symconst != NULL)
                        be_emit_char(env, '+');
-               be_emit_irprintf(env->emit, "%d", attr->offset);
+               be_emit_irprintf(env->emit, "0x%X", attr->offset);
        }
 }
 
@@ -1694,7 +1754,7 @@ void emit_ia32_Conv_I2I(ia32_emit_env_t *env, const ir_node *node) {
                        be_emit_cstring(env, "\tmov");
                        be_emit_string(env, sign_suffix);
                        ia32_emit_mode_suffix_mode(env, smaller_mode);
-                       be_emit_cstring(env, "l %");
+                       be_emit_cstring(env, "l ");
                        ia32_emit_am(env, node);
                        be_emit_cstring(env, ", ");
                        ia32_emit_dest_register(env, node, 0);
@@ -2190,25 +2250,8 @@ void ia32_emit_block_header(ia32_emit_env_t *env, ir_node *block, ir_node *prev)
        int           i, arity;
        ir_exec_freq  *exec_freq = env->cg->birg->exec_freq;
 
-       need_label = 1;
        n_cfgpreds = get_Block_n_cfgpreds(block);
-       if (n_cfgpreds == 0) {
-               need_label = 0;
-       } else if (n_cfgpreds == 1) {
-               ir_node *pred       = get_Block_cfgpred(block, 0);
-               ir_node *pred_block = get_nodes_block(pred);
-
-               /* we don't need labels for fallthrough blocks, however switch-jmps
-                * are no fallthroughs */
-               if(pred_block == prev &&
-                               !(is_Proj(pred) && is_ia32_SwitchJmp(get_Proj_pred(pred)))) {
-                       need_label = 0;
-               } else {
-                       need_label = 1;
-               }
-       } else {
-               need_label = 1;
-       }
+       need_label = (n_cfgpreds != 0);
 
        if (should_align_block(env, block, prev)) {
                assert(need_label);