introduce arm_emitf
authorMatthias Braun <matthias.braun@kit.edu>
Wed, 18 Jul 2012 12:12:49 +0000 (14:12 +0200)
committerMatthias Braun <matthias.braun@kit.edu>
Wed, 18 Jul 2012 14:48:10 +0000 (16:48 +0200)
ir/be/arm/arm_emitter.c
ir/be/arm/arm_emitter.h
ir/be/arm/arm_spec.pl

index eebb947..c504abc 100644 (file)
@@ -67,19 +67,19 @@ static void arm_emit_register(const arch_register_t *reg)
        be_emit_string(arch_register_get_name(reg));
 }
 
-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);
@@ -102,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;
@@ -124,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;
@@ -139,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;
@@ -178,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);
 
@@ -250,6 +250,146 @@ 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 != '\0')
+                       ++format;
+               be_emit_string_len(start, format-start);
+               if (*format == '\0')
+                       break;
+               ++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;
+               }
+
+               case '\n':
+                       be_emit_char('\n');
+                       be_emit_write_line();
+                       be_emit_char('\t');
+                       break;
+
+               default:
+unknown:
+                       panic("unknown format conversion in arm_emitf()");
+               }
+       }
+       va_end(ap);
+       be_emit_finish_line_gas(node);
+}
+
 /**
  * Emit a SymConst.
  */
@@ -268,24 +408,13 @@ static void emit_arm_SymConst(const ir_node *irn)
        }
 
        /* 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);
 }
 
 /**
@@ -293,28 +422,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 = set_insert(sym_or_tv_t, 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);
 }
 
 /**
@@ -325,24 +446,6 @@ 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.
  */
@@ -404,21 +507,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) {
                if (be_options.verbose_asm) {
-                       be_emit_cstring("\t/* fallthrough to ");
-                       arm_emit_cfop_target(proj_false);
-                       be_emit_cstring(" */");
-                       be_emit_finish_line_gas(proj_false);
+                       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);
        }
 }
 
@@ -438,11 +534,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 */
@@ -454,27 +545,9 @@ 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]);
-
        if (be_options.verbose_asm) {
-               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);
+               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" );
@@ -489,90 +562,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;
        }
 }
@@ -580,10 +585,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);
 }
@@ -593,22 +595,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)
@@ -622,21 +617,12 @@ 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");
                }
        } 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");
        }
@@ -644,29 +630,10 @@ static void emit_be_Copy(const ir_node *irn)
 
 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)
@@ -683,31 +650,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);
 }
@@ -720,12 +679,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);
        }
 }
 
@@ -737,16 +691,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");
 }
 
 
@@ -760,15 +707,10 @@ 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);
-               be_emit_finish_line_gas(node);
+               arm_emitf(node, "b %t", node);
        } else {
                if (be_options.verbose_asm) {
-                       be_emit_cstring("\t/* fallthrough to ");
-                       arm_emit_cfop_target(node);
-                       be_emit_cstring(" */");
-                       be_emit_finish_line_gas(node);
+                       arm_emitf(node, "/* fallthrough to %t */", node);
                }
        }
 }
index 9de9978..7cf437a 100644 (file)
 
 #include "bearch_arm_t.h"
 
-void arm_emit_float_load_store_mode(const ir_node *node);
-void arm_emit_float_arithmetic_mode(const ir_node *node);
-void arm_emit_symconst(const ir_node *node);
-void arm_emit_source_register(const ir_node *node, int pos);
-void arm_emit_dest_register(const ir_node *node, int pos);
-void arm_emit_offset(const ir_node *node);
-void arm_emit_shift(const ir_node *node);
-void arm_emit_shifter_operand(const ir_node *node);
-void arm_emit_load_mode(const ir_node *node);
-void arm_emit_store_mode(const ir_node *node);
+/**
+ * emit assembler instructions with format string. Automatically indents
+ * instructions and adds debug comments at the end (in verbose-asm mode).
+ * Format specifiers:
+ *
+ * fmt  parameter               output
+ * ---- ----------------------  ---------------------------------------------
+ * %%                           %
+ * %r   const arch_register_t*  register
+ * %Sx  <node>                  source register x
+ * %Dx  <node>                  destination register x
+ * %O   <node>                  shifter operand
+ * %I   <node>                  symconst immediate
+ * %o   <node>                  load/store offset
+ * %C   const sym_or_tv_t*      constant
+ * %t   const ir_node*          controlflow target
+ * %m   ir_mode*                fpa mode postfix
+ * %s   const char*             string
+ * %u   unsigned int            unsigned int
+ * %d   signed int              signed int
+ * %X   signed int              signed int (hexadecimal)
+ */
+void arm_emitf(const ir_node *node, const char *format, ...);
 
 void arm_gen_routine(ir_graph *irg);
 
index 1956d3e..7a27875 100644 (file)
@@ -49,21 +49,7 @@ $mode_fp    = "mode_F";
 );
 
 %emit_templates = (
-       FM  => "${arch}_emit_float_load_store_mode(node);",
-       AM  => "${arch}_emit_float_arithmetic_mode(node);",
-       LM  => "${arch}_emit_load_mode(node);",
-       SM  => "${arch}_emit_store_mode(node);",
        SO  => "${arch}_emit_shifter_operand(node);",
-       S0  => "${arch}_emit_source_register(node, 0);",
-       SC  => "${arch}_emit_symconst(node);",
-       S1  => "${arch}_emit_source_register(node, 1);",
-       S2  => "${arch}_emit_source_register(node, 2);",
-       S3  => "${arch}_emit_source_register(node, 3);",
-       S4  => "${arch}_emit_source_register(node, 4);",
-       D0  => "${arch}_emit_dest_register(node, 0);",
-       D1  => "${arch}_emit_dest_register(node, 1);",
-       D2  => "${arch}_emit_dest_register(node, 2);",
-       O   => "${arch}_emit_offset(node);",
 );
 
 $default_attr_type = "arm_attr_t";
@@ -193,7 +179,7 @@ my %cmp_shifter_operand_constructors = (
 
 Add => {
        irn_flags => [ "rematerializable" ],
-       emit      => '. add %D0, %S0, %SO',
+       emit      => 'add %D0, %S0, %O',
        mode      => $mode_gp,
        attr_type => "arm_shifter_operand_t",
        constructors => \%binop_shifter_operand_constructors,
@@ -202,21 +188,21 @@ Add => {
 Mul => {
        irn_flags => [ "rematerializable" ],
        reg_req   => { in => [ "gp", "gp" ], out => [ "!in_r1" ] },
-       emit      =>'. mul %D0, %S0, %S1',
+       emit      => 'mul %D0, %S0, %S1',
        mode      => $mode_gp,
 },
 
 Smull => {
        irn_flags => [ "rematerializable" ],
        reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
-       emit      =>'. smull %D0, %D1, %S0, %S1',
+       emit      => 'smull %D0, %D1, %S0, %S1',
        outs      => [ "low", "high" ],
 },
 
 Umull => {
        irn_flags => [ "rematerializable" ],
        reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
-       emit      =>'umull %D0, %D1, %S0, %S1',
+       emit      =>'umull %D0, %D1, %S0, %S1',
        outs      => [ "low", "high" ],
        mode      => $mode_gp,
 },
@@ -224,13 +210,13 @@ Umull => {
 Mla => {
        irn_flags => [ "rematerializable" ],
        reg_req   => { in => [ "gp", "gp", "gp" ], out => [ "!in_r1" ] },
-       emit      =>'mla %D0, %S0, %S1, %S2',
+       emit      =>'mla %D0, %S0, %S1, %S2',
        mode      => $mode_gp,
 },
 
 And => {
        irn_flags => [ "rematerializable" ],
-       emit      => '. and %D0, %S0, %SO',
+       emit      => 'and %D0, %S0, %O',
        mode      => $mode_gp,
        attr_type => "arm_shifter_operand_t",
        constructors => \%binop_shifter_operand_constructors,
@@ -238,7 +224,7 @@ And => {
 
 Or => {
        irn_flags => [ "rematerializable" ],
-       emit      => '. orr %D0, %S0, %SO',
+       emit      => 'orr %D0, %S0, %O',
        mode      => $mode_gp,
        attr_type => "arm_shifter_operand_t",
        constructors => \%binop_shifter_operand_constructors,
@@ -246,7 +232,7 @@ Or => {
 
 Eor => {
        irn_flags => [ "rematerializable" ],
-       emit      => '. eor %D0, %S0, %SO',
+       emit      => 'eor %D0, %S0, %O',
        mode      => $mode_gp,
        attr_type => "arm_shifter_operand_t",
        constructors => \%binop_shifter_operand_constructors,
@@ -254,7 +240,7 @@ Eor => {
 
 Bic => {
        irn_flags => [ "rematerializable" ],
-       emit      => '. bic %D0, %S0, %SO',
+       emit      => 'bic %D0, %S0, %O',
        mode      => $mode_gp,
        attr_type => "arm_shifter_operand_t",
        constructors => \%binop_shifter_operand_constructors,
@@ -262,7 +248,7 @@ Bic => {
 
 Sub => {
        irn_flags => [ "rematerializable" ],
-       emit      => '. sub %D0, %S0, %SO',
+       emit      => 'sub %D0, %S0, %O',
        mode      => $mode_gp,
        attr_type => "arm_shifter_operand_t",
        constructors => \%binop_shifter_operand_constructors,
@@ -270,7 +256,7 @@ Sub => {
 
 Rsb => {
        irn_flags => [ "rematerializable" ],
-       emit      => '. rsb %D0, %S0, %SO',
+       emit      => 'rsb %D0, %S0, %O',
        mode      => $mode_gp,
        attr_type => "arm_shifter_operand_t",
        constructors => \%binop_shifter_operand_constructors,
@@ -279,7 +265,7 @@ Rsb => {
 Mov => {
        irn_flags => [ "rematerializable" ],
        arity     => "variable",
-       emit      => '. mov %D0, %SO',
+       emit      => 'mov %D0, %O',
        mode      => $mode_gp,
        attr_type => "arm_shifter_operand_t",
        constructors => \%unop_shifter_operand_constructors,
@@ -289,7 +275,7 @@ Mvn => {
        irn_flags => [ "rematerializable" ],
        attr_type => "arm_shifter_operand_t",
        arity     => "variable",
-       emit      => '. mvn %D0, %SO',
+       emit      => 'mvn %D0, %O',
        mode      => $mode_gp,
        constructors => \%unop_shifter_operand_constructors,
 },
@@ -297,7 +283,7 @@ Mvn => {
 Clz => {
        irn_flags => [ "rematerializable" ],
        reg_req   => { in => [ "gp" ], out => [ "gp" ] },
-       emit      =>'. clz %D0, %S0',
+       emit      => 'clz %D0, %S0',
        mode      => $mode_gp,
 },
 
@@ -311,8 +297,8 @@ LinkMovPC => {
        attr         => "arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot",
        custominit   => "init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);\n".
                        "\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);",
-       emit         => "mov lr, pc\n".
-                       ". mov pc, %SO",
+       emit         => "mov lr, pc\n".
+                       "mov pc, %O",
 },
 
 # mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function
@@ -324,8 +310,8 @@ LinkLdrPC => {
        attr_type    => "arm_load_store_attr_t",
        attr         => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
        custominit   => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);",
-       emit         => "mov lr, pc\n".
-                       ". ldr pc, %SO",
+       emit         => "mov lr, pc\n".
+                       "ldr pc, %O",
 },
 
 Bl => {
@@ -335,7 +321,7 @@ Bl => {
        attr_type  => "arm_SymConst_attr_t",
        attr       => "ir_entity *entity, int symconst_offset",
        custominit => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);",
-       emit       => '. bl %SC',
+       emit       => 'bl %I',
 },
 
 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
@@ -343,7 +329,7 @@ EmptyReg => {
        op_flags  => [ "constlike" ],
        irn_flags => [ "rematerializable" ],
        reg_req   => { out => [ "gp" ] },
-       emit      => '/* %D0 now available for calculations */',
+       emit      => '/* %D0 now available for calculations */',
        cmp_attr  => 'return 1;',
        mode      => $mode_gp,
 },
@@ -377,7 +363,7 @@ SymConst => {
 
 Cmp => {
        irn_flags    => [ "rematerializable", "modify_flags" ],
-       emit         => '. cmp %S0, %SO',
+       emit         => 'cmp %S0, %O',
        mode         => $mode_flags,
        attr_type    => "arm_cmp_attr_t",
        constructors => \%cmp_shifter_operand_constructors,
@@ -385,7 +371,7 @@ Cmp => {
 
 Tst => {
        irn_flags    => [ "rematerializable", "modify_flags" ],
-       emit         => '. tst %S0, %SO',
+       emit         => 'tst %S0, %O',
        mode         => $mode_flags,
        attr_type    => "arm_cmp_attr_t",
        constructors => \%cmp_shifter_operand_constructors,
@@ -426,7 +412,7 @@ Ldr => {
        ins       => [ "ptr", "mem" ],
        outs      => [ "res", "M" ],
        reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
-       emit      => '. ldr%LM %D0, [%S0, #%O]',
+       emit      => 'ldr%ML %D0, [%S0, #%o]',
        attr_type => "arm_load_store_attr_t",
        attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
 },
@@ -437,7 +423,7 @@ Str => {
        ins       => [ "ptr", "val", "mem" ],
        outs      => [ "M" ],
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
-       emit      => '. str%SM %S1, [%S0, #%O]',
+       emit      => 'str%MS %S1, [%S0, #%o]',
        mode      => "mode_M",
        attr_type => "arm_load_store_attr_t",
        attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
@@ -448,7 +434,7 @@ StoreStackM4Inc => {
        irn_flags => [ "rematerializable" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
-       emit      => 'stmfd %S0!, {%S1, %S2, %S3, %S4}',
+       emit      => 'stmfd %S0!, {%S1, %S2, %S3, %S4}',
        outs      => [ "ptr", "M" ],
 },
 
@@ -457,7 +443,7 @@ LoadStackM3Epilogue => {
        irn_flags => [ "rematerializable" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
-       emit      => 'ldmfd %S0, {%D0, %D1, %D2}',
+       emit      => 'ldmfd %S0, {%D0, %D1, %D2}',
        outs      => [ "res0", "res1", "res2", "M" ],
 },
 
@@ -466,7 +452,7 @@ LoadStackM3Epilogue => {
 Adf => {
        irn_flags => [ "rematerializable" ],
        reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
-       emit      => '. adf%AM %D0, %S0, %S1',
+       emit      => 'adf%MA %D0, %S0, %S1',
        attr_type => "arm_farith_attr_t",
        attr      => "ir_mode *op_mode",
        mode      => $mode_fp,
@@ -475,7 +461,7 @@ Adf => {
 Muf => {
        irn_flags => [ "rematerializable" ],
        reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
-       emit      =>'. muf%AM %D0, %S0, %S1',
+       emit      => 'muf%MA %D0, %S0, %S1',
        attr_type => "arm_farith_attr_t",
        attr      => "ir_mode *op_mode",
        mode      => $mode_fp,
@@ -484,7 +470,7 @@ Muf => {
 Suf => {
        irn_flags => [ "rematerializable" ],
        reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
-       emit      => '. suf%AM %D0, %S0, %S1',
+       emit      => 'suf%MA %D0, %S0, %S1',
        attr_type => "arm_farith_attr_t",
        attr      => "ir_mode *op_mode",
        mode      => $mode_fp,
@@ -492,7 +478,7 @@ Suf => {
 
 Dvf => {
        reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
-       emit      =>'. dvf%AM %D0, %S0, %S1',
+       emit      => 'dvf%MA %D0, %S0, %S1',
        outs      => [ "res", "M" ],
        attr_type => "arm_farith_attr_t",
        attr      => "ir_mode *op_mode",
@@ -502,7 +488,7 @@ Dvf => {
 Mvf => {
        irn_flags => [ "rematerializable" ],
        reg_req   => { in => [ "fpa" ], out => [ "fpa" ] },
-       emit      => '. mvf%AM %S0, %D0',
+       emit      => 'mvf%MA %S0, %D0',
        attr_type => "arm_farith_attr_t",
        attr      => "ir_mode *op_mode",
        mode      => $mode_fp,
@@ -511,7 +497,7 @@ Mvf => {
 FltX => {
        irn_flags => [ "rematerializable" ],
        reg_req   => { in => [ "gp" ], out => [ "fpa" ] },
-       emit      => '. flt%AM %D0, %S0',
+       emit      => 'flt%MA %D0, %S0',
        attr_type => "arm_farith_attr_t",
        attr      => "ir_mode *op_mode",
        mode      => $mode_fp,
@@ -524,7 +510,7 @@ Cmfe => {
        attr      => "bool ins_permuted",
        init_attr => "init_arm_cmp_attr(res, ins_permuted, false);",
        reg_req   => { in => [ "fpa", "fpa" ], out => [ "flags" ] },
-       emit      => 'cmfe %S0, %S1',
+       emit      => 'cmfe %S0, %S1',
 },
 
 Ldf => {
@@ -533,7 +519,7 @@ Ldf => {
        ins       => [ "ptr", "mem" ],
        outs      => [ "res", "M" ],
        reg_req   => { in => [ "gp", "none" ], out => [ "fpa", "none" ] },
-       emit      => '. ldf%FM %D0, [%S0, #%O]',
+       emit      => 'ldf%MF %D0, [%S0, #%o]',
        attr_type => "arm_load_store_attr_t",
        attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
 },
@@ -545,7 +531,7 @@ Stf => {
        outs      => [ "M" ],
        mode      => "mode_M",
        reg_req   => { in => [ "gp", "fpa", "none" ], out => [ "none" ] },
-       emit      => '. stf%FM %S1, [%S0, #%O]',
+       emit      => 'stf%MF %S1, [%S0, #%o]',
        attr_type => "arm_load_store_attr_t",
        attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
 },