Prefer get_mode_null() over get_tarval_null().
[libfirm] / ir / be / ia32 / ia32_emitter.c
index a0f2732..188a9c0 100644 (file)
  * @brief       This file implements the ia32 node emitter.
  * @author      Christian Wuerdig, Matthias Braun
  * @version     $Id$
+ *
+ * Summary table for x86 floatingpoint compares:
+ *   pnc_Eq  => !P && E
+ *   pnc_Lt  => !P && B
+ *   pnc_Le  => !P && BE
+ *   pnc_Gt  => A
+ *   pnc_Ge  => AE
+ *   pnc_Lg  => P || NE
+ *   pnc_Leg => NP  (ordered)
+ *   pnc_Uo  => P
+ *   pnc_Ue  => E
+ *   pnc_Ul  => B
+ *   pnc_Ule => BE
+ *   pnc_Ug  => P || A
+ *   pnc_Uge => P || AE
+ *   pnc_Ne  => NE
  */
 #include "config.h"
 
@@ -64,8 +80,6 @@
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
-#define BLOCK_PREFIX ".L"
-
 #define SNPRINTF_BUF_LEN 128
 
 static const ia32_isa_t *isa;
@@ -201,7 +215,7 @@ static const arch_register_t *get_out_reg(const ir_node *irn, int pos)
 static char *get_unique_label(char *buf, size_t buflen, const char *prefix)
 {
        static unsigned long id = 0;
-       snprintf(buf, buflen, "%s%lu", prefix, ++id);
+       snprintf(buf, buflen, "%s%s%lu", be_gas_get_private_prefix(), prefix, ++id);
        return buf;
 }
 
@@ -282,11 +296,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_visibility(entity) == ir_visibility_external) {
                        be_emit_cstring("@INDNTPOFF");
                } else {
                        be_emit_cstring("@NTPOFF");
@@ -421,10 +434,13 @@ void ia32_emit_x87_mode_suffix(const ir_node *node)
 
        if (mode_is_float(mode)) {
                switch (get_mode_size_bits(mode)) {
-                       case 32: be_emit_char('s'); return;
-                       case 64: be_emit_char('l'); return;
-                       case 80:
-                       case 96: be_emit_char('t'); return;
+                       case  32: be_emit_char('s'); return;
+                       case  64: be_emit_char('l'); return;
+                       /* long doubles have different sizes due to alignment on different
+                        * platforms. */
+                       case  80:
+                       case  96:
+                       case 128: be_emit_char('t'); return;
                }
        } else {
                assert(mode_is_int(mode));
@@ -442,7 +458,7 @@ void ia32_emit_x87_mode_suffix(const ir_node *node)
 static char get_xmm_mode_suffix(ir_mode *mode)
 {
        assert(mode_is_float(mode));
-       switch(get_mode_size_bits(mode)) {
+       switch (get_mode_size_bits(mode)) {
        case 32: return 's';
        case 64: return 'd';
        default: panic("Invalid XMM mode");
@@ -494,27 +510,13 @@ static ir_node *get_cfop_target_block(const ir_node *irn)
        return get_irn_link(irn);
 }
 
-/**
- * Emits a block label for the given block.
- */
-static void ia32_emit_block_name(const ir_node *block)
-{
-       if (has_Block_entity(block)) {
-               ir_entity *entity = get_Block_entity(block);
-               be_gas_emit_entity(entity);
-       } else {
-               be_emit_cstring(BLOCK_PREFIX);
-               be_emit_irprintf("%ld", get_irn_node_nr(block));
-       }
-}
-
 /**
  * Emits the target label for a control flow node.
  */
 static void ia32_emit_cfop_target(const ir_node *node)
 {
        ir_node *block = get_cfop_target_block(node);
-       ia32_emit_block_name(block);
+       be_gas_emit_block_name(block);
 }
 
 /*
@@ -683,8 +685,8 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...)
                        break;
 
                ++fmt;
-               while (1) {
-                       switch(*fmt) {
+               for (;;) {
+                       switch (*fmt) {
                        case '*': mod |= EMIT_ALTERNATE_AM; break;
                        case '#': mod |= EMIT_RESPECT_LS;   break;
                        case 'l': mod |= EMIT_LONG;         break;
@@ -712,10 +714,10 @@ emit_AM:
                                                break;
 
                                        case 'R': {
+                                               const arch_register_t *reg = va_arg(ap, const arch_register_t*);
                                                if (get_ia32_op_type(node) == ia32_AddrModeS) {
                                                        goto emit_AM;
                                                } else {
-                                                       const arch_register_t *reg = va_arg(ap, const arch_register_t*);
                                                        if (mod & EMIT_ALTERNATE_AM)
                                                                be_emit_char('*');
                                                        emit_register(reg, NULL);
@@ -861,7 +863,7 @@ void ia32_emit_binop(const ir_node *node)
  */
 void ia32_emit_x87_binop(const ir_node *node)
 {
-       switch(get_ia32_op_type(node)) {
+       switch (get_ia32_op_type(node)) {
                case ia32_Normal:
                        {
                                const ia32_x87_attr_t *x87_attr = get_ia32_x87_attr_const(node);
@@ -1003,16 +1005,10 @@ static pn_Cmp ia32_get_negated_pnc(pn_Cmp pnc)
        return get_negated_pnc(pnc, mode);
 }
 
-void ia32_emit_cmp_suffix_node(const ir_node *node,
-                               int flags_pos)
+void ia32_emit_cmp_suffix_node(const ir_node *node, int flags_pos)
 {
-       const ia32_attr_t *attr = get_ia32_attr_const(node);
-
        pn_Cmp pnc = get_ia32_condcode(node);
-
        pnc = determine_final_pnc(node, flags_pos, pnc);
-       if (attr->data.ins_permuted)
-               pnc = ia32_get_negated_pnc(pnc);
 
        ia32_emit_cmp_suffix(pnc);
 }
@@ -1192,7 +1188,9 @@ static void emit_ia32_CMovcc(const ir_node *node)
 
        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 */
+        * 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);
 
@@ -1285,7 +1283,7 @@ static void generate_jump_table(jmp_tbl_t *tbl, const ir_node *node)
        const ir_edge_t    *edge;
 
        /* fill the table structure */
-       get_unique_label(tbl->label, SNPRINTF_BUF_LEN, ".TBL_");
+       get_unique_label(tbl->label, SNPRINTF_BUF_LEN, "TBL_");
        tbl->defProj      = NULL;
        tbl->num_branches = get_irn_n_edges(node) - 1;
        tbl->branches     = XMALLOCNZ(branch_t, tbl->num_branches);
@@ -1413,7 +1411,7 @@ static const char* emit_asm_operand(const ir_node *node, const char *s)
        c = *(++s);
 
        /* parse modifiers */
-       switch(c) {
+       switch (c) {
        case 0:
                ir_fprintf(stderr, "Warning: asm text (%+F) ends with %%\n", node);
                be_emit_char('%');
@@ -1492,7 +1490,7 @@ static const char* emit_asm_operand(const ir_node *node, const char *s)
        /* emit it */
        if (modifier != 0) {
                be_emit_char('%');
-               switch(modifier) {
+               switch (modifier) {
                case 'b':
                        reg_name = ia32_get_mapped_reg_name(isa->regs_8bit, reg);
                        break;
@@ -1533,7 +1531,7 @@ static void emit_ia32_Asm(const ir_node *node)
        if (s[0] != '\t')
                be_emit_char('\t');
 
-       while(*s != 0) {
+       while (*s != 0) {
                if (*s == '%') {
                        s = emit_asm_operand(node, s);
                } else {
@@ -1687,7 +1685,7 @@ static void emit_be_IncSP(const ir_node *node)
 
 static inline bool is_unknown_reg(const arch_register_t *reg)
 {
-       if(reg == &ia32_gp_regs[REG_GP_UKNWN]
+       if (reg == &ia32_gp_regs[REG_GP_UKNWN]
                        || reg == &ia32_xmm_regs[REG_XMM_UKNWN]
                        || reg == &ia32_vfp_regs[REG_VFP_UKNWN])
                return true;
@@ -1879,10 +1877,14 @@ static void emit_ia32_ClimbFrame(const ir_node *node)
 
        ia32_emitf(node, "\tmovl %S0, %D0\n");
        ia32_emitf(node, "\tmovl $%u, %S1\n", attr->count);
-       ia32_emitf(NULL, BLOCK_PREFIX "%ld:\n", get_irn_node_nr(node));
+       be_gas_emit_block_name(node);
+       be_emit_cstring(":\n");
+       be_emit_write_line();
        ia32_emitf(node, "\tmovl (%D0), %D0\n");
        ia32_emitf(node, "\tdec %S1\n");
-       ia32_emitf(node, "\tjnz " BLOCK_PREFIX "%ld\n", get_irn_node_nr(node));
+       be_emit_cstring("\tjnz ");
+       be_gas_emit_block_name(node);
+       be_emit_finish_line_gas(node);
 }
 
 static void emit_be_Return(const ir_node *node)
@@ -2076,7 +2078,7 @@ static int should_align_block(const ir_node *block)
                return 0;
 
        n_cfgpreds = get_Block_n_cfgpreds(block);
-       for(i = 0; i < n_cfgpreds; ++i) {
+       for (i = 0; i < n_cfgpreds; ++i) {
                const ir_node *pred      = get_Block_cfgpred_block(block, i);
                double         pred_freq = get_block_execfreq(exec_freq, pred);
 
@@ -2138,14 +2140,14 @@ static void ia32_emit_block_header(ir_node *block)
        }
 
        if (need_label) {
-               ia32_emit_block_name(block);
+               be_gas_emit_block_name(block);
                be_emit_char(':');
 
                be_emit_pad_comment();
                be_emit_cstring("   /* ");
        } else {
                be_emit_cstring("\t/* ");
-               ia32_emit_block_name(block);
+               be_gas_emit_block_name(block);
                be_emit_cstring(": ");
        }
 
@@ -2244,9 +2246,11 @@ 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");
+       get_unique_label(pic_base_label, sizeof(pic_base_label), "PIC_BASE");
 
        be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi));
        be_gas_emit_function_prolog(entity, ia32_cg_config.function_alignment);
@@ -2288,7 +2292,7 @@ void ia32_gen_routine(ia32_code_gen_t *ia32_cg, ir_graph *irg)
                        ia32_emit_exc_label(exc_list[i].exc_instr);
                        be_emit_char('\n');
                        be_emit_cstring("\t.long ");
-                       ia32_emit_block_name(exc_list[i].block);
+                       be_gas_emit_block_name(exc_list[i].block);
                        be_emit_char('\n');
                }
        }
@@ -2413,11 +2417,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_visibility(entity) == ir_visibility_external) {
                        be_emit_cstring("@INDNTPOFF");
                } else {
                        be_emit_cstring("@NTPOFF");
@@ -2439,7 +2442,7 @@ static void bemit_entity(ir_entity *entity, bool entity_sign, int offset,
 static void bemit_jmp_destination(const ir_node *dest_block)
 {
        be_emit_cstring("\t.long ");
-       ia32_emit_block_name(dest_block);
+       be_gas_emit_block_name(dest_block);
        be_emit_cstring(" - . - 4\n");
        be_emit_write_line();
 }