bechordal: Remove the parameter iteration, which is always 0, from post_spill().
[libfirm] / ir / be / arm / arm_emitter.c
index 40d414e..4558bc5 100644 (file)
@@ -45,7 +45,7 @@
 #include "beblocksched.h"
 #include "beirg.h"
 #include "begnuas.h"
-#include "be_dbgout.h"
+#include "bedwarf.h"
 
 #include "arm_emitter.h"
 #include "arm_optimize.h"
@@ -57,8 +57,6 @@
 
 #include "benode.h"
 
-#define SNPRINTF_BUF_LEN 128
-
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
 static set       *sym_or_tv;
@@ -66,22 +64,22 @@ static arm_isa_t *isa;
 
 static void arm_emit_register(const arch_register_t *reg)
 {
-       be_emit_string(arch_register_get_name(reg));
+       be_emit_string(reg->name);
 }
 
-void arm_emit_source_register(const ir_node *node, int pos)
+static void arm_emit_source_register(const ir_node *node, int pos)
 {
        const arch_register_t *reg = arch_get_irn_register_in(node, pos);
        arm_emit_register(reg);
 }
 
-void arm_emit_dest_register(const ir_node *node, int pos)
+static void arm_emit_dest_register(const ir_node *node, int pos)
 {
        const arch_register_t *reg = arch_get_irn_register_out(node, pos);
        arm_emit_register(reg);
 }
 
-void arm_emit_offset(const ir_node *node)
+static void arm_emit_offset(const ir_node *node)
 {
        const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
        assert(attr->base.is_load_store);
@@ -104,19 +102,19 @@ static void arm_emit_fpa_postfix(const ir_mode *mode)
        be_emit_char(c);
 }
 
-void arm_emit_float_load_store_mode(const ir_node *node)
+static void arm_emit_float_load_store_mode(const ir_node *node)
 {
        const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
        arm_emit_fpa_postfix(attr->load_store_mode);
 }
 
-void arm_emit_float_arithmetic_mode(const ir_node *node)
+static void arm_emit_float_arithmetic_mode(const ir_node *node)
 {
        const arm_farith_attr_t *attr = get_arm_farith_attr_const(node);
        arm_emit_fpa_postfix(attr->mode);
 }
 
-void arm_emit_symconst(const ir_node *node)
+static void arm_emit_symconst(const ir_node *node)
 {
        const arm_SymConst_attr_t *symconst = get_arm_SymConst_attr_const(node);
        ir_entity                 *entity   = symconst->entity;
@@ -126,7 +124,7 @@ void arm_emit_symconst(const ir_node *node)
        /* TODO do something with offset */
 }
 
-void arm_emit_load_mode(const ir_node *node)
+static void arm_emit_load_mode(const ir_node *node)
 {
        const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
        ir_mode *mode      = attr->load_store_mode;
@@ -141,7 +139,7 @@ void arm_emit_load_mode(const ir_node *node)
        }
 }
 
-void arm_emit_store_mode(const ir_node *node)
+static void arm_emit_store_mode(const ir_node *node)
 {
        const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
        ir_mode *mode      = attr->load_store_mode;
@@ -180,7 +178,7 @@ static void emit_shf_mod_name(arm_shift_modifier_t mod)
        panic("can't emit this shf_mod_name %d", (int) mod);
 }
 
-void arm_emit_shifter_operand(const ir_node *node)
+static void arm_emit_shifter_operand(const ir_node *node)
 {
        const arm_shifter_operand_t *attr = get_arm_shifter_operand_attr_const(node);
 
@@ -252,6 +250,150 @@ static void emit_constant_name(const sym_or_tv_t *entry)
        be_emit_irprintf("%sC%u", be_gas_get_private_prefix(), entry->label);
 }
 
+/**
+ * Returns the target block for a control flow node.
+ */
+static ir_node *get_cfop_target_block(const ir_node *irn)
+{
+       return (ir_node*)get_irn_link(irn);
+}
+
+/**
+ * Emit the target label for a control flow node.
+ */
+static void arm_emit_cfop_target(const ir_node *irn)
+{
+       ir_node *block = get_cfop_target_block(irn);
+
+       be_gas_emit_block_name(block);
+}
+
+void arm_emitf(const ir_node *node, const char *format, ...)
+{
+       va_list ap;
+       va_start(ap, format);
+       be_emit_char('\t');
+       for (;;) {
+               const char *start = format;
+               while (*format != '%' && *format != '\n'  && *format != '\0')
+                       ++format;
+               be_emit_string_len(start, format - start);
+
+               if (*format == '\0')
+                       break;
+
+               if (*format == '\n') {
+                       ++format;
+                       be_emit_char('\n');
+                       be_emit_write_line();
+                       be_emit_char('\t');
+                       continue;
+               }
+
+               ++format;
+
+               switch (*format++) {
+               case '%':
+                       be_emit_char('%');
+                       break;
+
+               case 'S': {
+                       if (*format < '0' || '9' <= *format)
+                               goto unknown;
+                       unsigned const pos = *format++ - '0';
+                       arm_emit_source_register(node, pos);
+                       break;
+               }
+
+               case 'D': {
+                       if (*format < '0' || '9' <= *format)
+                               goto unknown;
+                       unsigned const pos = *format++ - '0';
+                       arm_emit_dest_register(node, pos);
+                       break;
+               }
+
+               case 'I':
+                       arm_emit_symconst(node);
+                       break;
+
+               case 'o':
+                       arm_emit_offset(node);
+                       break;
+
+               case 'O':
+                       arm_emit_shifter_operand(node);
+                       break;
+
+               case 'C': {
+                       const sym_or_tv_t *name = va_arg(ap, const sym_or_tv_t*);
+                       emit_constant_name(name);
+                       break;
+               }
+
+               case 'm': {
+                       ir_mode *mode = va_arg(ap, ir_mode*);
+                       arm_emit_fpa_postfix(mode);
+                       break;
+               }
+
+               case 'M':
+                       switch (*format++) {
+                       case 'L': arm_emit_load_mode(node);             break;
+                       case 'S': arm_emit_store_mode(node);            break;
+                       case 'A': arm_emit_float_arithmetic_mode(node); break;
+                       case 'F': arm_emit_float_load_store_mode(node); break;
+                       default:
+                               --format;
+                               goto unknown;
+                       }
+                       break;
+
+               case 'X': {
+                       int num = va_arg(ap, int);
+                       be_emit_irprintf("%X", num);
+                       break;
+               }
+
+               case 'u': {
+                       unsigned num = va_arg(ap, unsigned);
+                       be_emit_irprintf("%u", num);
+                       break;
+               }
+
+               case 'd': {
+                       int num = va_arg(ap, int);
+                       be_emit_irprintf("%d", num);
+                       break;
+               }
+
+               case 's': {
+                       const char *string = va_arg(ap, const char *);
+                       be_emit_string(string);
+                       break;
+               }
+
+               case 'r': {
+                       arch_register_t *reg = va_arg(ap, arch_register_t*);
+                       arm_emit_register(reg);
+                       break;
+               }
+
+               case 't': {
+                       const ir_node *n = va_arg(ap, const ir_node*);
+                       arm_emit_cfop_target(n);
+                       break;
+               }
+
+               default:
+unknown:
+                       panic("unknown format conversion");
+               }
+       }
+       va_end(ap);
+       be_emit_finish_line_gas(node);
+}
+
 /**
  * Emit a SymConst.
  */
@@ -263,31 +405,20 @@ static void emit_arm_SymConst(const ir_node *irn)
        key.u.entity  = attr->entity;
        key.is_entity = true;
        key.label     = 0;
-       entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
+       entry = set_insert(sym_or_tv_t, sym_or_tv, &key, sizeof(key), hash_ptr(key.u.generic));
        if (entry->label == 0) {
                /* allocate a label */
                entry->label = get_unique_label();
        }
 
        /* load the symbol indirect */
-       be_emit_cstring("\tldr ");
-       arm_emit_dest_register(irn, 0);
-       be_emit_cstring(", ");
-       emit_constant_name(entry);
-       be_emit_finish_line_gas(irn);
+       arm_emitf(irn, "ldr %D0, %C", entry);
 }
 
 static void emit_arm_FrameAddr(const ir_node *irn)
 {
        const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(irn);
-
-       be_emit_cstring("\tadd ");
-       arm_emit_dest_register(irn, 0);
-       be_emit_cstring(", ");
-       arm_emit_source_register(irn, 0);
-       be_emit_cstring(", ");
-       be_emit_irprintf("#0x%X", attr->fp_offset);
-       be_emit_finish_line_gas(irn);
+       arm_emitf(irn, "add %D0, %S0, #0x%X", attr->fp_offset);
 }
 
 /**
@@ -295,28 +426,20 @@ static void emit_arm_FrameAddr(const ir_node *irn)
  */
 static void emit_arm_fConst(const ir_node *irn)
 {
-       sym_or_tv_t key, *entry;
-       ir_mode *mode;
+       sym_or_tv_t key;
 
        key.u.tv      = get_fConst_value(irn);
        key.is_entity = false;
        key.label     = 0;
-       entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
+       sym_or_tv_t *entry = set_insert(sym_or_tv_t, sym_or_tv, &key, sizeof(key), hash_ptr(key.u.generic));
        if (entry->label == 0) {
                /* allocate a label */
                entry->label = get_unique_label();
        }
 
        /* load the tarval indirect */
-       mode = get_irn_mode(irn);
-       be_emit_cstring("\tldf");
-       arm_emit_fpa_postfix(mode);
-       be_emit_char(' ');
-
-       arm_emit_dest_register(irn, 0);
-       be_emit_cstring(", ");
-       emit_constant_name(entry);
-       be_emit_finish_line_gas(irn);
+       ir_mode *mode = get_irn_mode(irn);
+       arm_emitf(irn, "ldf%m %D0, %C", mode, entry);
 }
 
 /**
@@ -327,30 +450,11 @@ static ir_node *sched_next_block(const ir_node *block)
     return (ir_node*)get_irn_link(block);
 }
 
-/**
- * Returns the target block for a control flow node.
- */
-static ir_node *get_cfop_target_block(const ir_node *irn)
-{
-       return (ir_node*)get_irn_link(irn);
-}
-
-/**
- * Emit the target label for a control flow node.
- */
-static void arm_emit_cfop_target(const ir_node *irn)
-{
-       ir_node *block = get_cfop_target_block(irn);
-
-       be_gas_emit_block_name(block);
-}
-
 /**
  * Emit a Compare with conditional branch.
  */
 static void emit_arm_B(const ir_node *irn)
 {
-       const ir_edge_t *edge;
        const ir_node *proj_true  = NULL;
        const ir_node *proj_false = NULL;
        const ir_node *block;
@@ -407,19 +511,14 @@ static void emit_arm_B(const ir_node *irn)
        }
 
        /* emit the true proj */
-       be_emit_irprintf("\tb%s ", suffix);
-       arm_emit_cfop_target(proj_true);
-       be_emit_finish_line_gas(proj_true);
+       arm_emitf(irn, "b%s %t", suffix, proj_true);
 
        if (get_cfop_target_block(proj_false) == next_block) {
-               be_emit_cstring("\t/* fallthrough to ");
-               arm_emit_cfop_target(proj_false);
-               be_emit_cstring(" */");
-               be_emit_finish_line_gas(proj_false);
+               if (be_options.verbose_asm) {
+                       arm_emitf(irn, "/* fallthrough to %t */", proj_false);
+               }
        } else {
-               be_emit_cstring("\tb ");
-               arm_emit_cfop_target(proj_false);
-               be_emit_finish_line_gas(proj_false);
+               arm_emitf(irn, "b %t", proj_false);
        }
 }
 
@@ -439,11 +538,6 @@ static void emit_arm_CopyB(const ir_node *irn)
 {
        const arm_CopyB_attr_t *attr = get_arm_CopyB_attr_const(irn);
        unsigned size = attr->size;
-
-       const char *tgt = arch_register_get_name(arch_get_irn_register_in(irn, 0));
-       const char *src = arch_register_get_name(arch_get_irn_register_in(irn, 1));
-       const char *t0, *t1, *t2, *t3;
-
        const arch_register_t *tmpregs[4];
 
        /* collect the temporary registers and sort them, we need ascending order */
@@ -455,26 +549,10 @@ static void emit_arm_CopyB(const ir_node *irn)
        /* Note: R12 is always the last register because the RA did not assign higher ones */
        qsort((void *)tmpregs, 3, sizeof(tmpregs[0]), reg_cmp);
 
-       /* need ascending order */
-       t0 = arch_register_get_name(tmpregs[0]);
-       t1 = arch_register_get_name(tmpregs[1]);
-       t2 = arch_register_get_name(tmpregs[2]);
-       t3 = arch_register_get_name(tmpregs[3]);
-
-       be_emit_cstring("/* MemCopy (");
-       be_emit_string(src);
-       be_emit_cstring(")->(");
-       arm_emit_source_register(irn, 0);
-       be_emit_irprintf(" [%u bytes], Uses ", size);
-       be_emit_string(t0);
-       be_emit_cstring(", ");
-       be_emit_string(t1);
-       be_emit_cstring(", ");
-       be_emit_string(t2);
-       be_emit_cstring(", and ");
-       be_emit_string(t3);
-       be_emit_cstring("*/");
-       be_emit_finish_line_gas(NULL);
+       if (be_options.verbose_asm) {
+               arm_emitf(irn, "/* MemCopy (%S1)->(%S0) [%u bytes], Uses %r, %r, %r and %r */",
+                         size, tmpregs[0], tmpregs[1], tmpregs[2], tmpregs[3]);
+       }
 
        assert(size > 0 && "CopyB needs size > 0" );
 
@@ -488,90 +566,22 @@ static void emit_arm_CopyB(const ir_node *irn)
        case 0:
                break;
        case 1:
-               be_emit_cstring("\tldr ");
-               be_emit_string(t3);
-               be_emit_cstring(", [");
-               be_emit_string(src);
-               be_emit_cstring(", #0]");
-               be_emit_finish_line_gas(NULL);
-
-               be_emit_cstring("\tstr ");
-               be_emit_string(t3);
-               be_emit_cstring(", [");
-               be_emit_string(tgt);
-               be_emit_cstring(", #0]");
-               be_emit_finish_line_gas(irn);
+               arm_emitf(irn, "ldr %r, [%S1, #0]", tmpregs[3]);
+               arm_emitf(irn, "str %r, [%S0, #0]", tmpregs[3]);
                break;
        case 2:
-               be_emit_cstring("\tldmia ");
-               be_emit_string(src);
-               be_emit_cstring("!, {");
-               be_emit_string(t0);
-               be_emit_cstring(", ");
-               be_emit_string(t1);
-               be_emit_char('}');
-               be_emit_finish_line_gas(NULL);
-
-               be_emit_cstring("\tstmia ");
-               be_emit_string(tgt);
-               be_emit_cstring("!, {");
-               be_emit_string(t0);
-               be_emit_cstring(", ");
-               be_emit_string(t1);
-               be_emit_char('}');
-               be_emit_finish_line_gas(irn);
+               arm_emitf(irn, "ldmia %S1!, {%r, %r}", tmpregs[0], tmpregs[1]);
+               arm_emitf(irn, "stmia %S0!, {%r, %r}", tmpregs[0], tmpregs[1]);
                break;
        case 3:
-               be_emit_cstring("\tldmia ");
-               be_emit_string(src);
-               be_emit_cstring("!, {");
-               be_emit_string(t0);
-               be_emit_cstring(", ");
-               be_emit_string(t1);
-               be_emit_cstring(", ");
-               be_emit_string(t2);
-               be_emit_char('}');
-               be_emit_finish_line_gas(NULL);
-
-               be_emit_cstring("\tstmia ");
-               be_emit_string(tgt);
-               be_emit_cstring("!, {");
-               be_emit_string(t0);
-               be_emit_cstring(", ");
-               be_emit_string(t1);
-               be_emit_cstring(", ");
-               be_emit_string(t2);
-               be_emit_char('}');
-               be_emit_finish_line_gas(irn);
+               arm_emitf(irn, "ldmia %S1!, {%r, %r, %r}", tmpregs[0], tmpregs[1], tmpregs[2]);
+               arm_emitf(irn, "stmia %S0!, {%r, %r, %r}", tmpregs[0], tmpregs[1], tmpregs[2]);
                break;
        }
        size >>= 2;
        while (size) {
-               be_emit_cstring("\tldmia ");
-               be_emit_string(src);
-               be_emit_cstring("!, {");
-               be_emit_string(t0);
-               be_emit_cstring(", ");
-               be_emit_string(t1);
-               be_emit_cstring(", ");
-               be_emit_string(t2);
-               be_emit_cstring(", ");
-               be_emit_string(t3);
-               be_emit_char('}');
-               be_emit_finish_line_gas(NULL);
-
-               be_emit_cstring("\tstmia ");
-               be_emit_string(tgt);
-               be_emit_cstring("!, {");
-               be_emit_string(t0);
-               be_emit_cstring(", ");
-               be_emit_string(t1);
-               be_emit_cstring(", ");
-               be_emit_string(t2);
-               be_emit_cstring(", ");
-               be_emit_string(t3);
-               be_emit_char('}');
-               be_emit_finish_line_gas(irn);
+               arm_emitf(irn, "ldmia %S1!, {%r, %r, %r}", tmpregs[0], tmpregs[1], tmpregs[2], tmpregs[3]);
+               arm_emitf(irn, "stmia %S0!, {%r, %r, %r}", tmpregs[0], tmpregs[1], tmpregs[2], tmpregs[3]);
                --size;
        }
 }
@@ -579,10 +589,7 @@ static void emit_arm_CopyB(const ir_node *irn)
 static void emit_arm_SwitchJmp(const ir_node *irn)
 {
        const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(irn);
-       be_emit_cstring("\tldrls pc, [pc, ");
-       arm_emit_source_register(irn, 0);
-       be_emit_cstring(", asl #2]");
-       be_emit_finish_line_gas(irn);
+       arm_emitf(irn, "ldrls pc, [pc, %S0, asl #2]");
 
        be_emit_jump_table(irn, attr->table, NULL, get_cfop_target_block);
 }
@@ -592,22 +599,15 @@ static void emit_be_IncSP(const ir_node *irn)
 {
        int offs = -be_get_IncSP_offset(irn);
 
-       if (offs != 0) {
-               if (offs < 0) {
-                       be_emit_cstring("\tsub ");
-                       offs = -offs;
-               } else {
-                       be_emit_cstring("\tadd ");
-               }
-               arm_emit_dest_register(irn, 0);
-               be_emit_cstring(", ");
-               arm_emit_source_register(irn, 0);
-               be_emit_irprintf(", #0x%X", offs);
-               be_emit_finish_line_gas(irn);
-       } else {
-               /* omitted IncSP(0) */
+       if (offs == 0)
                return;
+
+       const char *op = "add";
+       if (offs < 0) {
+               op   = "sub";
+               offs = -offs;
        }
+       arm_emitf(irn, "%s %D0, %S0, #0x%X", op, offs);
 }
 
 static void emit_be_Copy(const ir_node *irn)
@@ -621,51 +621,23 @@ static void emit_be_Copy(const ir_node *irn)
 
        if (mode_is_float(mode)) {
                if (USE_FPA(isa)) {
-                       be_emit_cstring("\tmvf");
-                       be_emit_char(' ');
-                       arm_emit_dest_register(irn, 0);
-                       be_emit_cstring(", ");
-                       arm_emit_source_register(irn, 0);
-                       be_emit_finish_line_gas(irn);
+                       arm_emitf(irn, "mvf %D0, %S0");
                } else {
-                       panic("emit_be_Copy: move not supported for this mode");
+                       panic("move not supported for this mode");
                }
        } else if (mode_is_data(mode)) {
-               be_emit_cstring("\tmov ");
-               arm_emit_dest_register(irn, 0);
-               be_emit_cstring(", ");
-               arm_emit_source_register(irn, 0);
-               be_emit_finish_line_gas(irn);
+               arm_emitf(irn, "mov %D0, %S0");
        } else {
-               panic("emit_be_Copy: move not supported for this mode");
+               panic("move not supported for this mode");
        }
 }
 
 static void emit_be_Perm(const ir_node *irn)
 {
-       be_emit_cstring("\teor ");
-       arm_emit_source_register(irn, 0);
-       be_emit_cstring(", ");
-       arm_emit_source_register(irn, 0);
-       be_emit_cstring(", ");
-       arm_emit_source_register(irn, 1);
-       be_emit_finish_line_gas(NULL);
-
-       be_emit_cstring("\teor ");
-       arm_emit_source_register(irn, 1);
-       be_emit_cstring(", ");
-       arm_emit_source_register(irn, 0);
-       be_emit_cstring(", ");
-       arm_emit_source_register(irn, 1);
-       be_emit_finish_line_gas(NULL);
-
-       be_emit_cstring("\teor ");
-       arm_emit_source_register(irn, 0);
-       be_emit_cstring(", ");
-       arm_emit_source_register(irn, 0);
-       be_emit_cstring(", ");
-       arm_emit_source_register(irn, 1);
-       be_emit_finish_line_gas(irn);
+       arm_emitf(irn,
+               "eor %S0, %S0, %S1\n"
+               "eor %S1, %S0, %S1\n"
+               "eor %S0, %S0, %S1");
 }
 
 static void emit_be_MemPerm(const ir_node *node)
@@ -682,31 +654,23 @@ static void emit_be_MemPerm(const ir_node *node)
                panic("memperm with more than 12 inputs not supported yet");
 
        for (i = 0; i < memperm_arity; ++i) {
-               int offset;
-               ir_entity *entity = be_get_MemPerm_in_entity(node, i);
-
                /* spill register */
-               be_emit_irprintf("\tstr r%d, [sp, #-4]!", i);
-               be_emit_finish_line_gas(node);
+               arm_emitf(node, "str r%d, [sp, #-4]!", i);
                sp_change += 4;
                /* load from entity */
-               offset = get_entity_offset(entity) + sp_change;
-               be_emit_irprintf("\tldr r%d, [sp, #%d]", i, offset);
-               be_emit_finish_line_gas(node);
+               ir_entity *entity = be_get_MemPerm_in_entity(node, i);
+               int        offset = get_entity_offset(entity) + sp_change;
+               arm_emitf(node, "ldr r%d, [sp, #%d]", i, offset);
        }
 
        for (i = memperm_arity-1; i >= 0; --i) {
-               int        offset;
-               ir_entity *entity = be_get_MemPerm_out_entity(node, i);
-
                /* store to new entity */
-               offset = get_entity_offset(entity) + sp_change;
-               be_emit_irprintf("\tstr r%d, [sp, #%d]", i, offset);
-               be_emit_finish_line_gas(node);
+               ir_entity *entity = be_get_MemPerm_out_entity(node, i);
+               int        offset = get_entity_offset(entity) + sp_change;
+               arm_emitf(node, "str r%d, [sp, #%d]", i, offset);
                /* restore register */
-               be_emit_irprintf("\tldr r%d, [sp], #4", i);
+               arm_emitf(node, "ldr r%d, [sp], #4", i);
                sp_change -= 4;
-               be_emit_finish_line_gas(node);
        }
        assert(sp_change == 0);
 }
@@ -719,12 +683,7 @@ static void emit_be_Start(const ir_node *node)
 
        /* allocate stackframe */
        if (size > 0) {
-               be_emit_cstring("\tsub ");
-               arm_emit_register(&arm_registers[REG_SP]);
-               be_emit_cstring(", ");
-               arm_emit_register(&arm_registers[REG_SP]);
-               be_emit_irprintf(", #0x%X", size);
-               be_emit_finish_line_gas(node);
+               arm_emitf(node, "sub sp, sp, #0x%X", size);
        }
 }
 
@@ -736,16 +695,9 @@ static void emit_be_Return(const ir_node *node)
 
        /* deallocate stackframe */
        if (size > 0) {
-               be_emit_cstring("\tadd ");
-               arm_emit_register(&arm_registers[REG_SP]);
-               be_emit_cstring(", ");
-               arm_emit_register(&arm_registers[REG_SP]);
-               be_emit_irprintf(", #0x%X", size);
-               be_emit_finish_line_gas(node);
+               arm_emitf(node, "add sp, sp, #0x%X", size);
        }
-
-       be_emit_cstring("\tmov pc, lr");
-       be_emit_finish_line_gas(node);
+       arm_emitf(node, "mov pc, lr");
 }
 
 
@@ -759,14 +711,12 @@ static void emit_arm_Jmp(const ir_node *node)
        /* we have a block schedule */
        next_block = sched_next_block(block);
        if (get_cfop_target_block(node) != next_block) {
-               be_emit_cstring("\tb ");
-               arm_emit_cfop_target(node);
+               arm_emitf(node, "b %t", node);
        } else {
-               be_emit_cstring("\t/* fallthrough to ");
-               arm_emit_cfop_target(node);
-               be_emit_cstring(" */");
+               if (be_options.verbose_asm) {
+                       arm_emitf(node, "/* fallthrough to %t */", node);
+               }
        }
-       be_emit_finish_line_gas(node);
 }
 
 static void emit_nothing(const ir_node *irn)
@@ -794,7 +744,7 @@ static inline void set_emitter(ir_op *op, emit_func arm_emit_node)
 static void arm_register_emitters(void)
 {
        /* first clear the generic function pointer for all ops */
-       clear_irp_opcodes_generic_func();
+       ir_clear_opcodes_generic_func();
 
        /* register all emitter functions defined in spec */
        arm_register_spec_emitters();
@@ -829,11 +779,11 @@ static void arm_emit_node(const ir_node *irn)
 
        if (op->ops.generic) {
                emit_func *emit = (emit_func *)op->ops.generic;
-               be_dbg_set_dbg_info(get_irn_dbg_info(irn));
+               be_dwarf_location(get_irn_dbg_info(irn));
                (*emit)(irn);
        } else {
                panic("Error: No emit handler for node %+F (graph %+F)\n",
-                     irn, current_ir_graph);
+                     irn, get_irn_irg(irn));
        }
 }
 
@@ -842,13 +792,9 @@ static void arm_emit_node(const ir_node *irn)
  */
 static void arm_emit_block_header(ir_node *block, ir_node *prev)
 {
-       int           n_cfgpreds;
-       int           need_label;
-       int           i, arity;
-       ir_graph      *irg       = get_irn_irg(block);
-       ir_exec_freq  *exec_freq = be_get_irg_exec_freq(irg);
+       bool need_label = false;
+       int  n_cfgpreds;
 
-       need_label = 0;
        n_cfgpreds = get_Block_n_cfgpreds(block);
        if (n_cfgpreds == 1) {
                ir_node *pred       = get_Block_cfgpred(block, 0);
@@ -858,38 +804,15 @@ static void arm_emit_block_header(ir_node *block, ir_node *prev)
                 * are no fallthroughs */
                if (pred_block == prev &&
                                !(is_Proj(pred) && is_arm_SwitchJmp(get_Proj_pred(pred)))) {
-                       need_label = 0;
+                       need_label = false;
                } else {
-                       need_label = 1;
+                       need_label = true;
                }
        } else {
-               need_label = 1;
+               need_label = true;
        }
 
-       if (need_label) {
-               be_gas_emit_block_name(block);
-               be_emit_char(':');
-
-               be_emit_pad_comment();
-               be_emit_cstring("   /* preds:");
-
-               /* emit list of pred blocks in comment */
-               arity = get_irn_arity(block);
-               for (i = 0; i < arity; ++i) {
-                       ir_node *predblock = get_Block_cfgpred_block(block, i);
-                       be_emit_irprintf(" %d", get_irn_node_nr(predblock));
-               }
-       } else {
-               be_emit_cstring("\t/* ");
-               be_gas_emit_block_name(block);
-               be_emit_cstring(": ");
-       }
-       if (exec_freq != NULL) {
-               be_emit_irprintf(" freq: %f",
-                                get_block_execfreq(exec_freq, block));
-       }
-       be_emit_cstring(" */\n");
-       be_emit_write_line();
+       be_gas_begin_block(block, need_label);
 }
 
 /**
@@ -898,10 +821,8 @@ static void arm_emit_block_header(ir_node *block, ir_node *prev)
  */
 static void arm_gen_block(ir_node *block, ir_node *prev_block)
 {
-       ir_node *irn;
-
        arm_emit_block_header(block, prev_block);
-       be_dbg_set_dbg_info(get_irn_dbg_info(block));
+       be_dwarf_location(get_irn_dbg_info(block));
        sched_foreach(block, irn) {
                arm_emit_node(irn);
        }
@@ -955,7 +876,7 @@ void arm_gen_routine(ir_graph *irg)
        /* create the block schedule */
        blk_sched = be_create_block_schedule(irg);
 
-       be_gas_emit_function_prolog(entity, 4);
+       be_gas_emit_function_prolog(entity, 4, NULL);
 
        irg_block_walk_graph(irg, arm_gen_labels, NULL, NULL);
 
@@ -975,11 +896,9 @@ void arm_gen_routine(ir_graph *irg)
 
        /* emit SymConst values */
        if (set_count(sym_or_tv) > 0) {
-               sym_or_tv_t *entry;
-
                be_emit_cstring("\t.align 2\n");
 
-               foreach_set(sym_or_tv, sym_or_tv_t*, entry) {
+               foreach_set(sym_or_tv, sym_or_tv_t, entry) {
                        emit_constant_name(entry);
                        be_emit_cstring(":\n");
                        be_emit_write_line();