Handle new ia32_isa_t type
[libfirm] / ir / be / ia32 / ia32_emitter.c
index 35c77e7..0153117 100644 (file)
 /* global arch_env for lc_printf functions */
 static const arch_env_t *arch_env = NULL;
 
+/** by default, we generate assembler code for the Linux gas */
+asm_flavour_t asm_flavour = ASM_LINUX_GAS;
+
+/**
+ * Switch to a new section
+ */
+void ia32_switch_section(FILE *F, section_t sec) {
+       static section_t curr_sec = NO_SECTION;
+  static const char *text[ASM_MAX][SECTION_MAX] = {
+               {
+                       ".section\t.text", ".section\t.data", ".section\t.rodata", ".section\t.text"
+               },
+               {
+                       ".section\t.text", ".section\t.data", ".section .rdata,\"dr\"", ".section\t.text"
+               }
+       };
+
+       if (curr_sec == sec)
+               return;
+
+       curr_sec = sec;
+       switch (sec) {
+
+       case NO_SECTION:
+               break;
+
+       case SECTION_TEXT:
+       case SECTION_DATA:
+       case SECTION_RODATA:
+       case SECTION_COMMON:
+               fprintf(F, "\t%s\n", text[asm_flavour][sec]);
+       }
+}
+
+static void ia32_dump_function_object(FILE *F, const char *name)
+{
+       switch (asm_flavour) {
+       case ASM_LINUX_GAS:
+               fprintf(F, "\t.type\t%s, @function\n", name);
+               break;
+       case ASM_MINGW_GAS:
+               fprintf(F, "\t.def\t%s;\t.scl\t2;\t.type\t32;\t.endef\n", name);
+               break;
+       }
+}
+
+static void ia32_dump_function_size(FILE *F, const char *name)
+{
+       switch (asm_flavour) {
+       case ASM_LINUX_GAS:
+               fprintf(F, "\t.size\t%s, .-%s\n", name, name);
+               break;
+       }
+}
+
 /*************************************************************
  *             _       _    __   _          _
  *            (_)     | |  / _| | |        | |
@@ -78,6 +133,17 @@ static const arch_register_t *get_in_reg(const ir_node *irn, int pos) {
        reg = arch_get_irn_register(arch_env, op);
 
        assert(reg && "no in register found");
+
+       /* in case of unknown: just return a register */
+       if (REGS_ARE_EQUAL(reg, &ia32_gp_regs[REG_GP_UKNWN]))
+               reg = &ia32_gp_regs[REG_EAX];
+       else if (REGS_ARE_EQUAL(reg, &ia32_xmm_regs[REG_XMM_UKNWN]))
+               reg = &ia32_xmm_regs[REG_XMM0];
+       else if (REGS_ARE_EQUAL(reg, &ia32_vfp_regs[REG_VFP_UKNWN]))
+               reg = &ia32_vfp_regs[REG_VF0];
+       else if (REGS_ARE_EQUAL(reg, &ia32_st_regs[REG_ST_UKNWN]))
+               reg = &ia32_st_regs[REG_ST0];
+
        return reg;
 }
 
@@ -326,7 +392,12 @@ char *ia32_emit_binop(const ir_node *n, ia32_emit_env_t *env) {
                                snprintf(buf, SNPRINTF_BUF_LEN, "%s, %s", get_ia32_cnst(n), ia32_emit_am(n, env));
                        }
                        else {
-                               lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%4S, %s", n, ia32_emit_am(n, env));
+                               if (PRODUCES_RESULT(n)) {
+                                       lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%1D, %s", n, ia32_emit_am(n, env));
+                               }
+                               else {
+                                       lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%4S, %s", n, ia32_emit_am(n, env));
+                               }
                        }
                        break;
                case ia32_AddrModeD:
@@ -925,7 +996,7 @@ static void emit_ia32_SwitchJmp(const ir_node *irn, ia32_emit_env_t *emit_env) {
                snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* get jump table entry as target */");
                IA32_DO_EMIT(irn);
 
-               fprintf(F, "\t.section\t.rodata\n");
+               ia32_switch_section(F, SECTION_RODATA);
                fprintf(F, "\t.align 4\n");
 
                fprintf(F, "%s:\n", tbl.label);
@@ -945,8 +1016,7 @@ static void emit_ia32_SwitchJmp(const ir_node *irn, ia32_emit_env_t *emit_env) {
                        snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* case %d */", last_value);
                        IA32_DO_EMIT(irn);
                }
-
-               fprintf(F, "\n\t.text\n\n");
+               ia32_switch_section(F, SECTION_TEXT);
        }
        else {
                /* one jump is enough */
@@ -1061,12 +1131,17 @@ static void emit_CopyB_prolog(FILE *F, int rem, int size) {
  * Emit rep movsd instruction for memcopy.
  */
 static void emit_ia32_CopyB(const ir_node *irn, ia32_emit_env_t *emit_env) {
-       FILE   *F    = emit_env->out;
-       tarval *tv   = get_ia32_Immop_tarval(irn);
-       int     rem  = get_tarval_long(tv);
-       int     size = get_tarval_long(get_ia32_Immop_tarval(get_irn_n(irn, 2)));
+       FILE    *F         = emit_env->out;
+       tarval  *tv        = get_ia32_Immop_tarval(irn);
+       int      rem       = get_tarval_long(tv);
+       ir_node *size_node = get_irn_n(irn, 2);
+       int      size;
        char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
 
+       /* beware: size_node could be a be_Copy to fulfill constraints for ecx */
+       size_node = be_is_Copy(size_node) ? be_get_Copy_op(size_node) : size_node;
+       size      = get_tarval_long(get_ia32_Immop_tarval(size_node));
+
        emit_CopyB_prolog(F, rem, size);
 
        snprintf(cmd_buf, SNPRINTF_BUF_LEN, "rep movsd");
@@ -1420,13 +1495,14 @@ static void ia32_gen_block(ir_node *block, void *env) {
  */
 static void ia32_emit_func_prolog(FILE *F, ir_graph *irg) {
        entity     *irg_ent  = get_irg_entity(irg);
-       const char *irg_name = get_entity_name(irg_ent);
+       const char *irg_name = get_entity_ld_name(irg_ent);
 
-       fprintf(F, "\t.section\t.text\n");
+       fprintf(F, "\n");
+       ia32_switch_section(F, SECTION_TEXT);
        if (get_entity_visibility(irg_ent) == visibility_external_visible) {
                fprintf(F, ".globl %s\n", irg_name);
        }
-       fprintf(F, "\t.type\t%s, @function\n", irg_name);
+       ia32_dump_function_object(F, irg_name);
        fprintf(F, "%s:\n", irg_name);
 }
 
@@ -1434,10 +1510,11 @@ static void ia32_emit_func_prolog(FILE *F, ir_graph *irg) {
  * Emits code for function end
  */
 static void ia32_emit_func_epilog(FILE *F, ir_graph *irg) {
-       const char *irg_name = get_entity_name(get_irg_entity(irg));
+       const char *irg_name = get_entity_ld_name(get_irg_entity(irg));
 
        fprintf(F, "\tret\n");
-       fprintf(F, "\t.size\t%s, .-%s\n\n", irg_name, irg_name);
+       ia32_dump_function_size(F, irg_name);
+       fprintf(F, "\n");
 }
 
 /**
@@ -1476,7 +1553,7 @@ void ia32_gen_routine(FILE *F, ir_graph *irg, const ia32_code_gen_t *cg) {
        ia32_emit_func_prolog(F, irg);
        irg_block_walk_graph(irg, ia32_gen_labels, NULL, &emit_env);
 
-       if (cg->opt.extbb && cg->blk_sched) {
+       if ((cg->opt & IA32_OPT_EXTBB) && cg->blk_sched) {
                int i, n = ARR_LEN(cg->blk_sched);
 
                for (i = 0; i < n;) {