- Split bearch.h correctly into bearch.h and bearch_t.h
[libfirm] / ir / be / arm / arm_emitter.c
index b16eb89..5b93963 100644 (file)
@@ -19,6 +19,8 @@
 #include "irargs_t.h"
 
 #include "../besched.h"
+#include "../beblocksched.h"
+#include "../beirg_t.h"
 
 #include "arm_emitter.h"
 #include "gen_arm_emitter.h"
@@ -55,6 +57,9 @@ void arm_switch_section(FILE *f, sections sec) {
        case SECTION_DATA:
                fprintf(f, "\t.data\n");
                break;
+
+       default:
+               assert(0);
        }
 }
 
@@ -100,15 +105,13 @@ static const char *node_offset_to_str(ir_node *n, char *buf, int buflen) {
        ir_op *irn_op = get_irn_op(n);
 
        if (irn_op == op_be_StackParam) {
-               entity *ent = be_get_frame_entity(n);
-               offset = get_entity_offset_bytes(ent);
+               ir_entity *ent = be_get_frame_entity(n);
+               offset = get_entity_offset(ent);
        } else if (irn_op == op_be_Reload || irn_op == op_be_Spill) {
-               entity * ent = be_get_spill_entity(n);
-               offset = get_entity_offset_bytes(ent);
+               ir_entity *ent = be_get_frame_entity(n);
+               offset = get_entity_offset(ent);
        } else if (irn_op == op_be_IncSP) {
-               int offs = be_get_IncSP_offset(n);
-               be_stack_dir_t dir  = be_get_IncSP_direction(n);
-               offset = (dir == be_stack_dir_expand) ? -offs : offs;
+               offset = - be_get_IncSP_offset(n);
        } else {
                return "node_offset_to_str will fuer diesen Knotentyp noch implementiert werden";
        }
@@ -264,17 +267,17 @@ static int arm_shift_str(lc_appendable_t *app,
     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
 {
        char buffer[SNPRINTF_BUF_LEN];
-       ir_node            *X = arg->v_ptr;
+       ir_node            *irn = arg->v_ptr;
        arm_shift_modifier mod;
 
-       if (!X)
+       if (!irn)
                return lc_appendable_snadd(app, "(null)", 6);
 
-       mod = get_arm_shift_modifier(X);
+       mod = get_arm_shift_modifier(irn);
        if (ARM_HAS_SHIFT(mod)) {
-               long v = get_tarval_long(get_arm_value(X));
+               long v = get_tarval_long(get_arm_value(irn));
 
-               snprintf(buffer, sizeof(buffer), " %s #%ld", arm_shf_mod_name(mod), v);
+               snprintf(buffer, sizeof(buffer), ", %s #%ld", arm_shf_mod_name(mod), v);
                return lc_appendable_snadd(app, buffer, strlen(buffer));
        }
        return 0;
@@ -286,15 +289,24 @@ static int arm_shift_str(lc_appendable_t *app,
 static int arm_get_mode_suffix(lc_appendable_t *app,
     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
 {
-       ir_node *X = arg->v_ptr;
+       ir_node *irn = arg->v_ptr;
+       arm_attr_t *attr;
+       ir_mode *mode;
+       int bits;
 
-       if (!X)
+       if (! irn)
                return lc_appendable_snadd(app, "(null)", 6);
 
-       if (get_mode_size_bits(get_irn_mode(X)) == 32)
+       attr = get_arm_attr(irn);
+       mode = attr->op_mode ? attr->op_mode : get_irn_mode(irn);
+       bits = get_mode_size_bits(mode);
+
+       if (bits == 32)
                return lc_appendable_chadd(app, 's');
-       else
+       else if (bits == 64)
                return lc_appendable_chadd(app, 'd');
+       else
+               return lc_appendable_chadd(app, 'e');
 }
 
 /**
@@ -328,48 +340,35 @@ const lc_arg_env_t *arm_get_arg_env(void) {
 /**
  * Formated print of commands and comments.
  */
-static void arm_fprintf_format(FILE *F, char *cmd_buf, char *cmnt_buf, ir_node *irn) {
+static void arm_fprintf_format(FILE *F, const char *cmd_buf, const char *cmnt_buf, const ir_node *irn) {
        lc_efprintf(arm_get_arg_env(), F, "\t%-35s %-60s /* %+F (%G) */\n", cmd_buf, cmnt_buf, irn, irn);
 }
 
-/*
- * Add a number to a prefix. This number will not be used a second time.
+/**
+ * Returns a unique label. This number will not be used a second time.
  */
-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);
-       return buf;
+static unsigned get_unique_label(void) {
+       static unsigned id = 0;
+       return ++id;
 }
 
-
 /**
- * Returns the target label for a control flow node.
+ * Emit a SymConst
  */
-static char *get_cfop_target(const ir_node *irn, char *buf) {
-       ir_node *bl = get_irn_link(irn);
-
-       snprintf(buf, SNPRINTF_BUF_LEN, "BLOCK_%ld", get_irn_node_nr(bl));
-       return buf;
-}
-
-/************************************************************************/
-/* emit_arm                                                             */
-/************************************************************************/
-
 static void emit_arm_SymConst(ir_node *irn, void *env) {
        arm_emit_env_t *emit_env = env;
-       FILE *out = emit_env->out;
-       char buffer1[SNPRINTF_BUF_LEN];
-       char *skip_label = get_unique_label(buffer1, SNPRINTF_BUF_LEN, ".L");
-       char buffer2[SNPRINTF_BUF_LEN];
-       char *indi_label = get_unique_label(buffer2, SNPRINTF_BUF_LEN, ".L");
-       fprintf( out, "\tB %s\t\t\t\t\t/* start of indirect SymConst */\n", skip_label );
-       fprintf( out, "\t.align 2\n" );
-       fprintf( out, "%s:\n", indi_label );
-       lc_efprintf(arm_get_arg_env(), out, "\t.word\t%C\n", irn);
-       fprintf( out, "\t.align 2\n" );
-       fprintf( out, "%s:\n", skip_label );
-       lc_efprintf(arm_get_arg_env(), out, "\tLDR %1D, %s\t\t\t/* end of indirect SymConst */\n", irn, indi_label);
+       FILE *F = emit_env->out;
+       SymConstEntry *entry = obstack_alloc(&emit_env->obst, sizeof(*entry));
+       const lc_arg_env_t *arg_env = arm_get_arg_env();
+       char cmd_buf[256];
+
+       entry->label      = get_unique_label();
+       entry->symconst   = irn;
+       entry->next       = emit_env->symbols;
+       emit_env->symbols = entry;
+
+       lc_esnprintf(arg_env, cmd_buf, 256, "ldr %1D, .L%u", irn, entry->label);
+       arm_fprintf_format(F, cmd_buf, "/* indirect SymConst */", irn);
 }
 
 /**
@@ -410,21 +409,21 @@ static void emit_arm_CondJmp(ir_node *irn, void *env) {
 
        if (proj_num == pn_Cmp_False) {
                /* always false: should not happen */
-               fprintf(out, "\tB BLOCK_%ld\t\t\t/* false case */\n", get_irn_node_nr(false_block));
+               fprintf(out, "\tb BLOCK_%ld\t\t\t/* false case */\n", get_irn_node_nr(false_block));
        } else if (proj_num == pn_Cmp_True) {
                /* always true: should not happen */
-               fprintf(out, "\tB BLOCK_%ld\t\t\t/* true case */\n", get_irn_node_nr(true_block));
+               fprintf(out, "\tb BLOCK_%ld\t\t\t/* true case */\n", get_irn_node_nr(true_block));
        } else {
                ir_node *block = get_nodes_block(irn);
 
                if (mode_is_float(opmode)) {
                        suffix = "ICHWILLIMPLEMENTIERTWERDEN";
 
-                       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "FCMP %1S, %2S", irn, irn);
+                       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "fcmp %1S, %2S", irn, irn);
                        lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* Compare(%1S, %2S) -> FCPSR */", irn, irn );
                        arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
 
-                       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "FMSTAT", irn, irn);
+                       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "fmstat", irn, irn);
                        lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* FCSPR -> CPSR */");
                        arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
                } else {
@@ -433,23 +432,23 @@ static void emit_arm_CondJmp(ir_node *irn, void *env) {
                                proj_num = get_negated_pnc(proj_num, opmode);
                        }
                        switch(proj_num) {
-                               case pn_Cmp_Eq:  suffix = "EQ"; break;
-                               case pn_Cmp_Lt:  suffix = "LT"; break;
-                               case pn_Cmp_Le:  suffix = "LE"; break;
-                               case pn_Cmp_Gt:  suffix = "GT"; break;
-                               case pn_Cmp_Ge:  suffix = "GE"; break;
-                               case pn_Cmp_Lg:  suffix = "NE"; break;
-                               case pn_Cmp_Leg: suffix = "AL"; break;
-                       default: assert(0 && "komische Dinge geschehen"); suffix = "AL";
+                               case pn_Cmp_Eq:  suffix = "eq"; break;
+                               case pn_Cmp_Lt:  suffix = "lt"; break;
+                               case pn_Cmp_Le:  suffix = "le"; break;
+                               case pn_Cmp_Gt:  suffix = "gt"; break;
+                               case pn_Cmp_Ge:  suffix = "ge"; break;
+                               case pn_Cmp_Lg:  suffix = "ne"; break;
+                               case pn_Cmp_Leg: suffix = "al"; break;
+                       default: assert(0 && "komische Dinge geschehen"); suffix = "al";
                        }
 
-                       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "CMP %1S, %2S", irn, irn);
+                       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "cmp %1S, %2S", irn, irn);
                        lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* Compare(%1S, %2S) -> CPSR */", irn, irn );
                        arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
                }
 
                if (true_block == sched_next_block(block)) {
-                       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "B%s BLOCK_%d", suffix, get_irn_node_nr(true_block));
+                       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "b%s BLOCK_%d", suffix, get_irn_node_nr(true_block));
                        lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* false case */");
                        arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
 
@@ -457,7 +456,7 @@ static void emit_arm_CondJmp(ir_node *irn, void *env) {
                        arm_fprintf_format(out, "", cmnt_buf, irn);
                }
                else {
-                       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "B%s BLOCK_%d", suffix, get_irn_node_nr(true_block));
+                       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "b%s BLOCK_%d", suffix, get_irn_node_nr(true_block));
                        lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* true case */");
                        arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
 
@@ -466,7 +465,7 @@ static void emit_arm_CondJmp(ir_node *irn, void *env) {
                 arm_fprintf_format(out, "", cmnt_buf, irn);
             }
             else {
-                           lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "B BLOCK_%d", get_irn_node_nr(false_block));
+                           lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "b BLOCK_%d", get_irn_node_nr(false_block));
                            lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* false case */");
                            arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
             }
@@ -491,29 +490,29 @@ static void emit_arm_CopyB(ir_node *irn, void *env) {
        case 0:
                break;
        case 1:
-               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "LDR %%r12, [%2S, #0]!", irn);
+               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "ldr %%r12, [%2S, #0]!", irn);
                arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
-               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "STR  %%r12, [%1S, #0]!", irn);
+               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "str  %%r12, [%1S, #0]!", irn);
                arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
                break;
        case 2:
-               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "LDMIA %2S!, {%%r12, %3S}", irn, irn);
+               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "ldmia %2S!, {%%r12, %3S}", irn, irn);
                arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
-               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "STMIA %1S!, {%%r12, %3S}", irn, irn);
+               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "stmia %1S!, {%%r12, %3S}", irn, irn);
                arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
                break;
        case 3:
-               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "LDMIA %2S!, {%%r12, %3S, %4S}", irn, irn, irn);
+               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "ldmia %2S!, {%%r12, %3S, %4S}", irn, irn, irn);
                arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
-               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "STMIA %1S!, {%%r12, %3S, %4S}", irn, irn, irn);
+               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "stmia %1S!, {%%r12, %3S, %4S}", irn, irn, irn);
                arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
                break;
        }
        size >>= 2;
        while (size) {
-               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "LDMIA %2S!, {%%r12, %3S, %4S, %5S}", irn, irn, irn, irn);
+               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "ldmia %2S!, {%%r12, %3S, %4S, %5S}", irn, irn, irn, irn);
                arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
-               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "STMIA %1S!, {%%r12, %3S, %4S, %5S}", irn, irn, irn, irn);
+               lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "stmia %1S!, {%%r12, %3S, %4S, %5S}", irn, irn, irn, irn);
                arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
                --size;
        }
@@ -529,7 +528,7 @@ static void emit_arm_SwitchJmp(ir_node *irn, void *env) {
        ir_node **projs;
        int n_projs;
        int block_nr;
-       int default_block_num;
+       int default_block_num = -1;
 
        block_nr = get_irn_node_nr(irn);
        n_projs = get_arm_n_projs(irn);
@@ -545,32 +544,33 @@ static void emit_arm_SwitchJmp(ir_node *irn, void *env) {
 
                projs[get_Proj_proj(proj)] = proj;
        }
+       assert(default_block_num >= 0);
 
        // CMP %1S, n_projs - 1
        // BHI default
 
 
 
-       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "CMP %1S, #%u", irn, n_projs - 1);
+       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "cmp %1S, #%u", irn, n_projs - 1);
        lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "", irn);
-       lc_efprintf(arm_get_arg_env(), out, "\t%-35s %-60s /* %+F */\n", cmd_buf, cmnt_buf, irn);
+       arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
 
-       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "BHI BLOCK_%d", default_block_num);
+       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "bhi BLOCK_%d", default_block_num);
        lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "", irn);
-       lc_efprintf(arm_get_arg_env(), out, "\t%-35s %-60s /* %+F */\n", cmd_buf, cmnt_buf, irn);
+       arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
 
 
-       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "LDR %%r12, TABLE_%d_START", block_nr);
+       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "ldr %%r12, TABLE_%d_START", block_nr);
        lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "", irn);
-       lc_efprintf(arm_get_arg_env(), out, "\t%-35s %-60s /* %+F */\n", cmd_buf, cmnt_buf, irn);
+       arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
 
-       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "ADD %%r12, %%r12, %1S, LSL #2", irn);
+       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "add %%r12, %%r12, %1S, LSL #2", irn);
        lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "", irn);
-       lc_efprintf(arm_get_arg_env(), out, "\t%-35s %-60s /* %+F */\n", cmd_buf, cmnt_buf, irn);
+       arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
 
-       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "LDR %%r15, [%%r12, #0]");
+       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "ldr %%r15, [%%r12, #0]");
        lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "", irn);
-       lc_efprintf(arm_get_arg_env(), out, "\t%-35s %-60s /* %+F */\n", cmd_buf, cmnt_buf, irn);
+       arm_fprintf_format(out, cmd_buf, cmnt_buf, irn);
 
        // LDR %r12, .TABLE_X_START
        // ADD %r12, %r12, [%1S, LSL #2]
@@ -603,30 +603,31 @@ static void emit_arm_SwitchJmp(ir_node *irn, void *env) {
 static void emit_be_Call(ir_node *irn, void *env) {
        arm_emit_env_t *emit_env = env;
        FILE *F = emit_env->out;
-       entity *ent = be_Call_get_entity(irn);
+       ir_entity *ent = be_Call_get_entity(irn);
     char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
 
     if (ent)
-           lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "BL %s", get_entity_ld_name(ent));
+           lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "bl %s", get_entity_ld_name(ent));
     else
         lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "%1D", get_irn_n(irn, be_pos_Call_ptr));
     lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* %+F (be_Call) */", irn);
-    lc_efprintf(arm_get_arg_env(), F, "\t%-35s %-60s /* %G */\n", cmd_buf, cmnt_buf, irn);
+    arm_fprintf_format(F, cmd_buf, cmnt_buf, irn);
 }
 
 /** Emit an IncSP node */
 static void emit_be_IncSP(const ir_node *irn, arm_emit_env_t *emit_env) {
        FILE *F = emit_env->out;
-       unsigned offs = be_get_IncSP_offset(irn);
-       if (offs) {
+       int offs = be_get_IncSP_offset(irn);
+
+       if (offs != 0) {
                char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
-               lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "ADD %1D, %1S, #%O", irn, irn, irn );
+               lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "add %1D, %1S, #%O", irn, irn, irn );
                lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* IncSP(%O) */", irn);
-               lc_efprintf(arm_get_arg_env(), F, "\t%-35s %-60s /* %+F */\n", cmd_buf, cmnt_buf, irn);
+               arm_fprintf_format(F, cmd_buf, cmnt_buf, irn);
        } else {
                char cmnt_buf[SNPRINTF_BUF_LEN];
                lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* omitted IncSP(%O) */", irn);
-               lc_efprintf(arm_get_arg_env(), F, "\t%-35s %-60s /* %+F */\n", "", cmnt_buf, irn);
+               arm_fprintf_format(F, "", cmnt_buf, irn);
        }
 }
 
@@ -641,59 +642,83 @@ static void emit_be_IncSP(const ir_node *irn, arm_emit_env_t *emit_env) {
 static void emit_be_Copy(const ir_node *irn, arm_emit_env_t *emit_env) {
        FILE *F    = emit_env->out;
        ir_mode *mode = get_irn_mode(irn);
-       assert( (mode != mode_E) && "IEEE Extended FP not supported");
+       const lc_arg_env_t *arm_env = arm_get_arg_env();
+       char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
 
        if (get_in_reg(irn, 0) == get_out_reg(irn, 0)) {
-               char cmnt_buf[SNPRINTF_BUF_LEN];
-               lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* omitted Copy: %1S -> %1D */", irn, irn);
-               lc_efprintf(arm_get_arg_env(), F, "\t%-35s %-60s /* %+F */\n", "", cmnt_buf, irn);
+               lc_esnprintf(arm_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* omitted Copy: %1S -> %1D */", irn, irn);
+               lc_efprintf(arm_env, F, "\t%-35s %-60s /* %+F */\n", "", cmnt_buf, irn);
                return;
        }
 
-       if (mode == mode_F) {
-               char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
-               lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "FCPYS %1D, %1S", irn, irn);
-               lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* Copy: %1S -> %1D */", irn, irn);
-               lc_efprintf(arm_get_arg_env(), F, "\t%-35s %-60s /* %+F */\n", cmd_buf, cmnt_buf, irn);
-       } else if (mode == mode_D) {
-               char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
-               lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "FCPYD %1D, %1S", irn, irn);
-               lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* Copy: %1S -> %1D */", irn, irn);
-               lc_efprintf(arm_get_arg_env(), F, "\t%-35s %-60s /* %+F */\n", cmd_buf, cmnt_buf, irn);
+       if (mode_is_float(mode)) {
+               if (USE_FPA(emit_env->cg->isa)) {
+                       lc_esnprintf(arm_env, cmd_buf, SNPRINTF_BUF_LEN, "mvf%M %1D, %1S", irn, irn, irn);
+                       lc_esnprintf(arm_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* Copy: %1S -> %1D */", irn, irn);
+                       arm_fprintf_format(F, cmd_buf, cmnt_buf, irn);
+               }
+               else {
+                       assert(0 && "move not supported for this mode");
+               }
        } else if (mode_is_numP(mode)) {
-               char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
-               lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "MOV %1D, %1S", irn, irn);
-               lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* Copy: %1S -> %1D */", irn, irn);
-               lc_efprintf(arm_get_arg_env(), F, "\t%-35s %-60s /* %+F */\n", cmd_buf, cmnt_buf, irn);
+               lc_esnprintf(arm_env, cmd_buf, SNPRINTF_BUF_LEN, "mov %1D, %1S", irn, irn);
+               lc_esnprintf(arm_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* Copy: %1S -> %1D */", irn, irn);
+               arm_fprintf_format(F, cmd_buf, cmnt_buf, irn);
        } else {
                assert(0 && "move not supported for this mode");
        }
 //     emit_arm_Copy(irn, emit_env);
 }
 
+/**
+ * Emit code for a Spill.
+ */
 static void emit_be_Spill(const ir_node *irn, arm_emit_env_t *emit_env) {
        FILE *F = emit_env->out;
        ir_mode *mode = get_irn_mode(irn);
-       assert( (mode != mode_E) && "IEEE Extended FP not supported");
-       if (mode_is_dataM(mode)) {
-               char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
-               lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "STR %2S, [%1S, #%O]", irn, irn, irn );
-               lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* Spill(%2S) -> (%1S) */", irn, irn);
-               lc_efprintf(arm_get_arg_env(), F, "\t%-35s %-60s /* %+F */\n", cmd_buf, cmnt_buf, irn);
+       const lc_arg_env_t *arm_env = arm_get_arg_env();
+       char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
+
+       if (mode_is_float(mode)) {
+               if (USE_FPA(emit_env->cg->isa)) {
+                       lc_esnprintf(arm_env, cmd_buf, SNPRINTF_BUF_LEN, "stf %2S, [%1S, #%O]", irn, irn, irn );
+                       lc_esnprintf(arm_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* Spill(%2S) -> (%1S) */", irn, irn);
+                       arm_fprintf_format(F, cmd_buf, cmnt_buf, irn);
+               }
+               else {
+                       assert(0 && "move not supported for this mode");
+               }
+       } else if (mode_is_dataM(mode)) {
+               lc_esnprintf(arm_env, cmd_buf, SNPRINTF_BUF_LEN, "str %2S, [%1S, #%O]", irn, irn, irn );
+               lc_esnprintf(arm_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* Spill(%2S) -> (%1S) */", irn, irn);
+               arm_fprintf_format(F, cmd_buf, cmnt_buf, irn);
        } else {
                assert(0 && "spill not supported for this mode");
        }
 }
 
+/**
+ * Emit code for a Reload.
+ */
 static void emit_be_Reload(const ir_node* irn, arm_emit_env_t *emit_env) {
        FILE *F = emit_env->out;
        ir_mode *mode = get_irn_mode(irn);
-       assert( (mode != mode_E) && "IEEE Extended FP not supported");
-       if (mode_is_dataM(mode)) {
-               char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
-               lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "LDR %1D, [%1S, #%O]", irn, irn, irn );
-               lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* Reload(%1S) -> (%1D) */", irn, irn);
-               lc_efprintf(arm_get_arg_env(), F, "\t%-35s %-60s /* %+F */\n", cmd_buf, cmnt_buf, irn);
+       const lc_arg_env_t *arm_env = arm_get_arg_env();
+       char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
+
+       if (mode_is_float(mode)) {
+               if (USE_FPA(emit_env->cg->isa)) {
+                       lc_esnprintf(arm_env, cmd_buf, SNPRINTF_BUF_LEN, "ldf %1D, [%1S, #%O]", irn, irn, irn );
+                       lc_esnprintf(arm_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* Reload(%1S) -> (%1D) */", irn, irn);
+                       arm_fprintf_format(F, cmd_buf, cmnt_buf, irn);
+               }
+               else {
+                       assert(0 && "move not supported for this mode");
+               }
+       } else if (mode_is_dataM(mode)) {
+               lc_esnprintf(arm_env, cmd_buf, SNPRINTF_BUF_LEN, "ldr %1D, [%1S, #%O]", irn, irn, irn );
+               lc_esnprintf(arm_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* Reload(%1S) -> (%1D) */", irn, irn);
+               arm_fprintf_format(F, cmd_buf, cmnt_buf, irn);
        } else {
                assert(0 && "reload not supported for this mode");
        }
@@ -701,22 +726,42 @@ static void emit_be_Reload(const ir_node* irn, arm_emit_env_t *emit_env) {
 
 static void emit_be_Perm(const ir_node* irn, arm_emit_env_t *emit_env) {
        FILE *F = emit_env->out;
-       ir_mode *mode = get_irn_mode(irn);
-       assert( (mode != mode_E) && "IEEE Extended FP not supported");
-       lc_efprintf(arm_get_arg_env(), F, "\tEOR %1S, %1S, %2S\t\t\t/* begin Perm(%1S, %2S) */\n", irn, irn, irn, irn, irn);
-       lc_efprintf(arm_get_arg_env(), F, "\tEOR %2S, %1S, %2S\n", irn, irn, irn);
-       lc_efprintf(arm_get_arg_env(), F, "\tEOR %1S, %1S, %2S\t\t\t/* end Perm(%1S, %2S) */\n", irn, irn, irn, irn, irn);
+       const lc_arg_env_t *arm_env = arm_get_arg_env();
+       char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
+
+       lc_esnprintf(arm_env, cmd_buf, SNPRINTF_BUF_LEN, "eor %1S, %1S, %2S", irn, irn, irn);
+       lc_esnprintf(arm_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* begin Perm(%1S, %2S) */", irn, irn);
+       arm_fprintf_format(F, cmd_buf, cmnt_buf, irn);
+
+       lc_esnprintf(arm_env, cmd_buf, SNPRINTF_BUF_LEN, "eor %2S, %1S, %2S", irn, irn, irn);
+       lc_esnprintf(arm_env, cmnt_buf, SNPRINTF_BUF_LEN, " ");
+       arm_fprintf_format(F, cmd_buf, cmnt_buf, irn);
+
+       lc_esnprintf(arm_env, cmd_buf, SNPRINTF_BUF_LEN, "eor %1S, %1S, %2S", irn, irn, irn);
+       lc_esnprintf(arm_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* end Perm(%1S, %2S) */", irn, irn);
+       arm_fprintf_format(F, cmd_buf, cmnt_buf, irn);
 }
 
 static void emit_be_StackParam(const ir_node *irn, arm_emit_env_t *emit_env) {
        FILE *F = emit_env->out;
        ir_mode *mode = get_irn_mode(irn);
-       char cmd_buf[256], cmnt_buf[SNPRINTF_BUF_LEN];
-       assert( (mode != mode_E) && "IEEE Extended FP not supported");
+       const lc_arg_env_t *arm_env = arm_get_arg_env();
+       char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
 
-       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "LDR %1D, [%1S, #%O]", irn, irn, irn );
-       lc_esnprintf(arm_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* StackParam: (%1S + %O) -> %1D */",irn , irn, irn, get_irn_n(irn, 0));
-       lc_efprintf(arm_get_arg_env(), F, "\t%-35s %-60s /* %+F */\n", cmd_buf, cmnt_buf, irn);
+       if (mode_is_float(mode)) {
+               if (USE_FPA(emit_env->cg->isa)) {
+                       lc_esnprintf(arm_env, cmd_buf, SNPRINTF_BUF_LEN, "ldf %1D, [%1S, #%O]", irn, irn, irn );
+                       lc_esnprintf(arm_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* StackParam: (%1S + %O) -> %1D */",irn , irn, irn, get_irn_n(irn, 0));
+                       arm_fprintf_format(F, cmd_buf, cmnt_buf, irn);
+               }
+               else {
+                       assert(0 && "move not supported for this mode");
+               }
+       } else {
+               lc_esnprintf(arm_env, cmd_buf, SNPRINTF_BUF_LEN, "ldr %1D, [%1S, #%O]", irn, irn, irn );
+               lc_esnprintf(arm_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* StackParam: (%1S + %O) -> %1D */",irn , irn, irn, get_irn_n(irn, 0));
+               arm_fprintf_format(F, cmd_buf, cmnt_buf, irn);
+       }
 }
 
 /************************************************************************/
@@ -724,17 +769,32 @@ static void emit_be_StackParam(const ir_node *irn, arm_emit_env_t *emit_env) {
 /************************************************************************/
 
 static void emit_Jmp(ir_node *irn, void *env) {
+       char cmd_buf[SNPRINTF_BUF_LEN];
        arm_emit_env_t *emit_env = env;
-       FILE *out = emit_env->out;
+       FILE *F = emit_env->out;
        const ir_edge_t *edge = get_irn_out_edge_first(irn);
+       const lc_arg_env_t *arm_env = arm_get_arg_env();
        ir_node *target_block = get_edge_src_irn(edge);
-       fprintf(out, "\tB BLOCK_%ld\t\t\t/* unconditional Jump */\n", get_irn_node_nr(target_block));
+
+       lc_esnprintf(arm_env, cmd_buf, SNPRINTF_BUF_LEN, "b BLOCK_%d", get_irn_node_nr(target_block));
+       arm_fprintf_format(F, cmd_buf, "/* unconditional Jump */", irn);
 }
 
-static void emit_silence(ir_node *irn, void *env) {
+static void emit_arm_fpaDbl2GP(const ir_node *n, arm_emit_env_t *env) {
+  FILE *F = env->out;
+  char cmd_buf[256];
+  const lc_arg_env_t *arg_env = arm_get_arg_env();
+
+  lc_esnprintf(arg_env, cmd_buf, 256, "stfd %1S, [sp, #-8]! ", n);
+  arm_fprintf_format(F, cmd_buf, "/* Push fp to stack */", n);
 
+  lc_esnprintf(arg_env, cmd_buf, 256, "ldmfd sp!, {%2D, %1D} ", n, n);
+  arm_fprintf_format(F, cmd_buf, "/* Pop destination */", n);
 }
 
+static void emit_silence(ir_node *irn, void *env) {
+
+}
 
 
 /***********************************************************************************
@@ -771,6 +831,7 @@ static void arm_register_emitters(void) {
 //     ARM_EMIT(Const);
        ARM_EMIT(SymConst);
        ARM_EMIT(SwitchJmp);
+       ARM_EMIT(fpaDbl2GP);
 
        /* benode emitter */
        BE_EMIT(Call);
@@ -839,7 +900,7 @@ void arm_gen_block(ir_node *block, void *env) {
  * Emits code for function start.
  */
 void arm_emit_start(FILE *F, ir_graph *irg) {
-       entity *ent = get_irg_entity(irg);
+       ir_entity *ent = get_irg_entity(irg);
        const char *irg_name = get_entity_ld_name(ent);
        arm_switch_section(F, SECTION_TEXT);
        fprintf(F, "\t.align  2\n");
@@ -853,6 +914,7 @@ void arm_emit_start(FILE *F, ir_graph *irg) {
  * Emits code for function end
  */
 void arm_emit_end(FILE *F, ir_graph *irg) {
+       fprintf(F, "\t.ident \"firmcc\"\n");
 }
 
 /**
@@ -871,9 +933,10 @@ void arm_gen_labels(ir_node *block, void *env) {
 
 
 /**
-* Main driver. Emits the code for one routine.
+ * Main driver. Emits the code for one routine.
  */
 void arm_gen_routine(FILE *F, ir_graph *irg, const arm_code_gen_t *cg) {
+       SymConstEntry *entry;
        arm_emit_env_t emit_env;
     ir_node **blk_sched;
     int i, n;
@@ -881,6 +944,8 @@ void arm_gen_routine(FILE *F, ir_graph *irg, const arm_code_gen_t *cg) {
        emit_env.out      = F;
        emit_env.arch_env = cg->arch_env;
        emit_env.cg       = cg;
+       emit_env.symbols  = NULL;
+       obstack_init(&emit_env.obst);
        FIRM_DBG_REGISTER(emit_env.mod, "firm.be.arm.emit");
 
        /* set the global arch_env (needed by print hooks) */
@@ -889,7 +954,7 @@ void arm_gen_routine(FILE *F, ir_graph *irg, const arm_code_gen_t *cg) {
        arm_register_emitters();
 
        /* create the block schedule. For now, we don't need it earlier. */
-       blk_sched = sched_create_block_schedule(cg->irg);
+       blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq);
 
        arm_emit_start(F, irg);
        irg_block_walk_graph(irg, arm_gen_labels, NULL, &emit_env);
@@ -907,5 +972,14 @@ void arm_gen_routine(FILE *F, ir_graph *irg, const arm_code_gen_t *cg) {
                arm_gen_block(block, &emit_env);
        }
 
-       arm_emit_end(F, irg);
+       /* emit SymConst values */
+       if (emit_env.symbols)
+               fprintf(F, "\t.align 2\n");
+
+       for (entry = emit_env.symbols; entry; entry = entry->next) {
+               fprintf(F, ".L%u:\n", entry->label);
+               lc_efprintf(arm_get_arg_env(), F, "\t.word\t%C\n", entry->symconst);
+       }
+
+       obstack_free(&emit_env.obst, NULL);
 }