Implemented basic FPA support
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 20 Apr 2006 13:40:30 +0000 (13:40 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 20 Apr 2006 13:40:30 +0000 (13:40 +0000)
ir/be/arm/arm_emitter.c
ir/be/arm/arm_emitter.h
ir/be/arm/arm_map_regs.c
ir/be/arm/arm_nodes_attr.h
ir/be/arm/arm_spec.pl
ir/be/arm/arm_transform.c
ir/be/arm/bearch_arm.c
ir/be/arm/bearch_arm_t.h

index b16eb89..038c031 100644 (file)
@@ -264,15 +264,15 @@ 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);
                return lc_appendable_snadd(app, buffer, strlen(buffer));
@@ -286,15 +286,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');
 }
 
 /**
@@ -332,13 +341,12 @@ static void arm_fprintf_format(FILE *F, char *cmd_buf, char *cmnt_buf, ir_node *
        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;
 }
 
 
@@ -352,24 +360,20 @@ static char *get_cfop_target(const ir_node *irn, char *buf) {
        return buf;
 }
 
-/************************************************************************/
-/* emit_arm                                                             */
-/************************************************************************/
-
+/**
+ * Emit a SymConst
+ */
 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);
+       SymConstEntry *entry = obstack_alloc(&emit_env->obst, sizeof(*entry));
+
+       entry->label      = get_unique_label();
+       entry->symconst   = irn;
+       entry->next       = emit_env->symbols;
+       emit_env->symbols = entry;
+
+       lc_efprintf(arm_get_arg_env(), out, "\tldr %1D, .L%u\t\t\t/* end of indirect SymConst */\n", irn, entry->label);
 }
 
 /**
@@ -410,21 +414,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 +437,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 +461,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 +470,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 +495,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;
        }
@@ -551,24 +555,24 @@ static void emit_arm_SwitchJmp(ir_node *irn, void *env) {
 
 
 
-       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);
 
-       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);
 
 
-       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);
 
-       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);
 
-       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);
 
@@ -607,7 +611,7 @@ static void emit_be_Call(ir_node *irn, void *env) {
     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);
@@ -620,7 +624,7 @@ static void emit_be_IncSP(const ir_node *irn, arm_emit_env_t *emit_env) {
        unsigned offs = be_get_IncSP_offset(irn);
        if (offs) {
                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);
        } else {
@@ -652,17 +656,17 @@ static void emit_be_Copy(const ir_node *irn, arm_emit_env_t *emit_env) {
 
        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(), 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(), 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);
        } 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(), 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);
        } else {
@@ -677,7 +681,7 @@ static void emit_be_Spill(const ir_node *irn, arm_emit_env_t *emit_env) {
        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(), 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);
        } else {
@@ -691,7 +695,7 @@ static void emit_be_Reload(const ir_node* irn, arm_emit_env_t *emit_env) {
        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(), 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);
        } else {
@@ -703,9 +707,9 @@ 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);
+       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);
 }
 
 static void emit_be_StackParam(const ir_node *irn, arm_emit_env_t *emit_env) {
@@ -714,7 +718,7 @@ static void emit_be_StackParam(const ir_node *irn, arm_emit_env_t *emit_env) {
        char cmd_buf[256], cmnt_buf[SNPRINTF_BUF_LEN];
        assert( (mode != mode_E) && "IEEE Extended FP not supported");
 
-       lc_esnprintf(arm_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "LDR %1D, [%1S, #%O]", irn, irn, irn );
+       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);
 }
@@ -728,13 +732,24 @@ static void emit_Jmp(ir_node *irn, void *env) {
        FILE *out = emit_env->out;
        const ir_edge_t *edge = get_irn_out_edge_first(irn);
        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));
+       fprintf(out, "\tb BLOCK_%ld\t\t\t/* unconditional Jump */\n", get_irn_node_nr(target_block));
 }
 
-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);
+  lc_efprintf(arg_env, F, "\t%-35s %-60s /* %+F (%+G) */\n", cmd_buf, "/* Push fp to stack */", n, n);
 
+  lc_esnprintf(arg_env, cmd_buf, 256, "ldmfd sp!, {%2D, %1D} ", n, n);
+  lc_efprintf(arg_env, F, "\t%-35s %-60s /* %+F (%+G) */\n", cmd_buf, "/* Pop destination */", n, n);
 }
 
+static void emit_silence(ir_node *irn, void *env) {
+
+}
 
 
 /***********************************************************************************
@@ -771,6 +786,7 @@ static void arm_register_emitters(void) {
 //     ARM_EMIT(Const);
        ARM_EMIT(SymConst);
        ARM_EMIT(SwitchJmp);
+       ARM_EMIT(fpaDbl2GP);
 
        /* benode emitter */
        BE_EMIT(Call);
@@ -853,6 +869,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 +888,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 +899,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) */
@@ -907,5 +927,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);
 }
index 8c0b414..8dad6d2 100644 (file)
@@ -1,18 +1,32 @@
 #ifndef _ARM_EMITTER_H_
 #define _ARM_EMITTER_H_
 
-#include "irargs_t.h"  // this also inlucdes <libcore/lc_print.h>
-#include "irnode.h"
+#include "firm_types.h"
+#include "irargs_t.h"
 #include "debug.h"
 
 #include "../bearch.h"
 
 #include "bearch_arm_t.h"
 
+/**
+ * A SymConst entry.
+ */
+typedef struct _SymConstEntry {
+       unsigned label;              /**< a label number for this label */
+       ir_node  *symconst;          /**< the node holding this label */
+       struct _SymConstEntry *next; /**< links all entries */
+} SymConstEntry;
+
+/**
+ * The ARM emitter environment.
+ */
 typedef struct _arm_emit_env_t {
-       FILE                      *out;
-       const arch_env_t          *arch_env;
-       const arm_code_gen_t      *cg;
+       FILE                      *out;      /**< the output stream */
+       const arch_env_t          *arch_env; /**< the architecture environment */
+       const arm_code_gen_t      *cg;       /**< the code generator object */
+       struct obstack            obst;      /**< an temporary store for SymConstEntries */
+       SymConstEntry             *symbols;  /**< list containing all SymConstEntries */
        DEBUG_ONLY(firm_dbg_module_t *mod;)
 } arm_emit_env_t;
 
@@ -25,12 +39,15 @@ const char *get_arm_in_reg_name(ir_node *irn, int pos);
 
 void arm_gen_routine(FILE *F, ir_graph *irg, const arm_code_gen_t *cg);
 
+/**
+ * Sections.
+ */
 typedef enum sections {
-       NO_SECTION,                     /**< no section selected yet. */
-       SECTION_TEXT,           /**< text section */
-       SECTION_DATA,           /**< data section */
-       SECTION_RODATA, /**< rodata section */
-       SECTION_COMMON, /**< common section */
+       NO_SECTION,      /**< no section selected yet. */
+       SECTION_TEXT,    /**< text section */
+       SECTION_DATA,    /**< data section */
+       SECTION_RODATA,  /**< rodata section */
+       SECTION_COMMON,  /**< common section */
 } sections;
 
 /**
index f8b7569..2ebbe23 100644 (file)
@@ -71,15 +71,15 @@ long arm_translate_proj_pos(const ir_node *proj) {
        ir_node *pred = get_Proj_pred(proj);
        long nr       = get_Proj_proj(proj);
 
-       if (is_arm_Load(pred) || is_arm_fLoad(pred)) {
+       if (is_arm_Load(pred) || is_arm_fpaLdf(pred)) {
                if (nr == pn_Load_res)
                        return 0;
                assert(0 && "unsupported Proj(Load) number");
        }
-       else if (is_arm_Store(pred) || is_arm_fStore(pred)) {
+       else if (is_arm_Store(pred) || is_arm_fpaStf(pred)) {
                return 0;
        }
-       else if (is_arm_fDiv(pred)) {
+       else if (is_arm_fpaDiv(pred) || is_arm_fpaRdv(pred)) {
                if (nr == pn_Quot_res)
                        return 0;
                else
index 89ab590..6b9fa45 100644 (file)
@@ -71,8 +71,9 @@ typedef struct _arm_attr_t {
 
        const arch_register_t **slots;      /**< register slots for assigned registers */
 
-       unsigned instr_fl;                                                                      /**< condition code, shift modifier */
-       tarval *value;                                                                                  /**< immediate */
+       ir_mode *op_mode;                   /**< operation mode */
+       unsigned instr_fl;                  /**< condition code, shift modifier */
+       tarval *value;                      /**< immediate */
        const char *symconst_label;
        int proj_num;
        int n_projs;
index 8701dd2..73e353e 100644 (file)
@@ -6,7 +6,6 @@
 
 $arch = "arm";
 
-# $comment_string = 'WIRHABENKEINEKOMMENTARE';
 $comment_string = '/*';
 
 # the number of additional opcodes you want to register
@@ -31,6 +30,8 @@ $comment_string = '/*';
 #   "reg_req"   => { "in" => [ "reg_class|register" ], "out" => [ "reg_class|register|in_rX" ] },
 #   "cmp_attr"  => "c source code for comparing node attributes",
 #   "emit"      => "emit code with templates",
+#   "attr"      => "attitional attribute arguments for constructor"
+#   "init_attr" => "emit attribute initialization template"
 #   "rd_constructor" => "c source code which constructs an ir_node"
 # },
 #
@@ -115,7 +116,7 @@ $comment_string = '/*';
                          { "name" => "pc", "type" => 6 }, # this is our program counter
                          { "mode" => "mode_Iu" }
                        ],
-  "fp"  => [
+  "fpa"  => [
                          { "name" => "f0", "type" => 1 },
                          { "name" => "f1", "type" => 1 },
                          { "name" => "f2", "type" => 1 },
@@ -124,7 +125,7 @@ $comment_string = '/*';
                          { "name" => "f5", "type" => 2 },
                          { "name" => "f6", "type" => 2 },
                          { "name" => "f7", "type" => 2 },
-                         { "mode" => "mode_D" }
+                         { "mode" => "mode_E" }
                        ]
 ); # %reg_classes
 
@@ -162,7 +163,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. ADD %D1, %S1, %S2%X0 /* Add(%S1, %S2) -> %D1, (%A1, %A2) */'
+  "emit"      => '. add %D1, %S1, %S2%X0 /* Add(%S1, %S2) -> %D1, (%A1, %A2) */'
 },
 
 "Add_i" => {
@@ -172,7 +173,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. ADD %D1, %S1, %C /* Add(%C, %S1) -> %D1, (%A1, const) */'
+  "emit"      => '. add %D1, %S1, %C /* Add(%C, %S1) -> %D1, (%A1, const) */'
 },
 
 "Mul" => {
@@ -180,7 +181,7 @@ $comment_string = '/*';
   "irn_flags" => "R",
   "comment"   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "!in_r1" ] },
-  "emit"      =>'. MUL %D1, %S1, %S2 /* Mul(%S1, %S2) -> %D1, (%A1, %A2) */'
+  "emit"      =>'. mul %D1, %S1, %S2 /* Mul(%S1, %S2) -> %D1, (%A1, %A2) */'
 },
 
 "Mla" => {
@@ -188,7 +189,7 @@ $comment_string = '/*';
   "irn_flags" => "R",
   "comment"   => "construct Mla: Mla(a, b, c) = a * b + c",
   "reg_req"   => { "in" => [ "gp", "gp", "gp" ], "out" => [ "!in_r1" ] },
-  "emit"      =>'. MLA %D1, %S1, %S2, %S3 /* Mla(%S1, %S2, %S3) -> %D1, (%A1, %A2, %A3) */'
+  "emit"      =>'. mla %D1, %S1, %S2, %S3 /* Mla(%S1, %S2, %S3) -> %D1, (%A1, %A2, %A3) */'
 },
 
 "And" => {
@@ -199,7 +200,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. AND %D1, %S1, %S2%X0 /* And(%S1, %S2) -> %D1, (%A1, %A2) */'
+  "emit"      => '. and %D1, %S1, %S2%X0 /* And(%S1, %S2) -> %D1, (%A1, %A2) */'
 },
 
 "And_i" => {
@@ -208,7 +209,7 @@ $comment_string = '/*';
   "attr"      => "tarval *tv",
   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. AND %D1, %S1, %C /* And(%C, %S1) -> %D1, (%A1, const) */',
+  "emit"      => '. and %D1, %S1, %C /* And(%C, %S1) -> %D1, (%A1, const) */',
   "cmp_attr"  => 'return attr_a->value != attr_b->value;'
 },
 
@@ -220,7 +221,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. ORR %D1, %S1, %S2%X0 /* Or(%S1, %S2) -> %D1, (%A1, %A2) */'
+  "emit"      => '. orr %D1, %S1, %S2%X0 /* Or(%S1, %S2) -> %D1, (%A1, %A2) */'
 },
 
 "Or_i" => {
@@ -230,7 +231,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
-  "emit"      => '. ORR %D1, %S1, %C /* Or(%C, %S1) -> %D1, (%A1, const) */'
+  "emit"      => '. orr %D1, %S1, %C /* Or(%C, %S1) -> %D1, (%A1, const) */'
 },
 
 "Eor" => {
@@ -241,7 +242,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. EOR %D1, %S1, %S2%X0 /* Xor(%S1, %S2) -> %D1, (%A1, %A2) */'
+  "emit"      => '. eor %D1, %S1, %S2%X0 /* Xor(%S1, %S2) -> %D1, (%A1, %A2) */'
 },
 
 "Eor_i" => {
@@ -251,7 +252,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
-  "emit"      => '. EOR %D1, %S1, %C /* Xor(%C, %S1) -> %D1, (%A1, const) */'
+  "emit"      => '. eor %D1, %S1, %C /* Xor(%C, %S1) -> %D1, (%A1, const) */'
 },
 
 # not commutative operations
@@ -263,7 +264,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. BIC %D1, %S1, %S2%X0 /* AndNot(%S1, %S2) -> %D1, (%A1, %A2) */'
+  "emit"      => '. bic %D1, %S1, %S2%X0 /* AndNot(%S1, %S2) -> %D1, (%A1, %A2) */'
 },
 
 "Bic_i" => {
@@ -272,7 +273,7 @@ $comment_string = '/*';
   "attr"      => "tarval *tv",
   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. BIC %D1, %S1, %C /* AndNot(%C, %S1) -> %D1, (%A1, const) */',
+  "emit"      => '. bic %D1, %S1, %C /* AndNot(%C, %S1) -> %D1, (%A1, const) */',
   "cmp_attr"  => 'return attr_a->value != attr_b->value;'
 },
 
@@ -283,7 +284,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. SUB %D1, %S1, %S2%X0 /* Sub(%S1, %S2) -> %D1, (%A1, %A2) */'
+  "emit"      => '. sub %D1, %S1, %S2%X0 /* Sub(%S1, %S2) -> %D1, (%A1, %A2) */'
 },
 
 "Sub_i" => {
@@ -293,7 +294,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. SUB %D1, %S1, %C /* Sub(%S1, %C) -> %D1, (%A1, const) */',
+  "emit"      => '. sub %D1, %S1, %C /* Sub(%S1, %C) -> %D1, (%A1, const) */',
 },
 
 "Rsb" => {
@@ -303,7 +304,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. RSB %D1, %S1, %S2%X0 /* Rsb(%S1, %S2) -> %D1, (%A1, %A2) */'
+  "emit"      => '. rsb %D1, %S1, %S2%X0 /* Rsb(%S1, %S2) -> %D1, (%A1, %A2) */'
 },
 
 "Rsb_i" => {
@@ -312,7 +313,7 @@ $comment_string = '/*';
   "attr"      => "tarval *tv",
   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. RSB %D1, %S1, %C /* Rsb(%S1, %C) -> %D1, (%A1, const) */',
+  "emit"      => '. rsb %D1, %S1, %C /* Rsb(%S1, %C) -> %D1, (%A1, const) */',
   "cmp_attr"  => 'return attr_a->value != attr_b->value;'
 },
 
@@ -320,28 +321,28 @@ $comment_string = '/*';
   "irn_flags" => "R",
   "comment"   => "construct Shl: Shl(a, b) = a << b",
   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. MOV %D1, %S1, LSL %S2\t/* Shl(%S1, %S2) -> %D1, (%A1, %A2) */'
+  "emit"      => '. mov %D1, %S1, LSL %S2\t/* Shl(%S1, %S2) -> %D1, (%A1, %A2) */'
 },
 
 "Shr" => {
   "irn_flags" => "R",
   "comment"   => "construct Shr: Shr(a, b) = a >> b",
   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
-  "emit"      => '. MOV %D1, %S1, LSR %S2 /* Shr(%S1, %S2) -> %D1, (%A1, %A2) */'
+  "emit"      => '. mov %D1, %S1, LSR %S2 /* Shr(%S1, %S2) -> %D1, (%A1, %A2) */'
 },
 
 "Shrs" => {
   "irn_flags" => "R",
   "comment"   => "construct Shrs: Shrs(a, b) = a >> b",
   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
-  "emit"      => '. MOV %D1, %S1, ASR %S2\t\t /* Shrs(%S1, %S2) -> %D1, (%A1, %A2) */'
+  "emit"      => '. mov %D1, %S1, ASR %S2\t\t /* Shrs(%S1, %S2) -> %D1, (%A1, %A2) */'
 },
 
 #"RotR" => {
 #  "irn_flags" => "R",
 #  "comment"   => "construct RotR: RotR(a, b) = a ROTR b",
 #  "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-#  "emit"      => '. MOV %D1, %S1, ROR %S2 /* RotR(%S1, %S2) -> %D1, (%A1, %A2) */'
+#  "emit"      => '. mov %D1, %S1, ROR %S2 /* RotR(%S1, %S2) -> %D1, (%A1, %A2) */'
 ##  "emit"      => '. ror %S1, %S2, %D1 /* RotR(%S1, %S2) -> %D1, (%A1, %A2) */'
 #},
 
@@ -366,7 +367,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. MOV %D1, %S1%X0\t/* Mov(%S1%X0) -> %D1, (%A1) */'
+  "emit"      => '. mov %D1, %S1%X0\t/* Mov(%S1%X0) -> %D1, (%A1) */'
 },
 
 "Mov_i" => {
@@ -375,7 +376,7 @@ $comment_string = '/*';
   "attr"      => "tarval *tv",
   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
   "reg_req"   => { "out" => [ "gp" ] },
-  "emit"      => '. MOV %D1, %C   /* Mov Const into register */',
+  "emit"      => '. mov %D1, %C   /* Mov Const into register */',
   "cmp_attr"  => 'return attr_a->value != attr_b->value;'
 },
 
@@ -386,7 +387,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
   "cmp_attr"  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-  "emit"      => '. MVN %D1, %S1%X0 /* ~(%S1%X0) -> %D1, (%A1) */'
+  "emit"      => '. mvn %D1, %S1%X0 /* ~(%S1%X0) -> %D1, (%A1) */'
 },
 
 "Mvn_i" => {
@@ -396,7 +397,7 @@ $comment_string = '/*';
   "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
   "reg_req"   => { "out" => [ "gp" ] },
-  "emit"      => '. MVN %D1, %C   /* Mov ~Const into register */',
+  "emit"      => '. mvn %D1, %C   /* Mov ~Const into register */',
 },
 
 "Abs" => {
@@ -404,8 +405,8 @@ $comment_string = '/*';
   "comment"   => "construct Abs: Abs(a) = |a|",
   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
   "emit"      =>
-'. MOVS %S1, %S1, #0 /* set condition flag */\n
-. RSBMI %D1, %S1, #0 /* Neg(%S1) -> %D1, (%A1) */'
+'. movs %S1, %S1, #0 /* set condition flag */\n
+. rsbmi %D1, %S1, #0 /* Neg(%S1) -> %D1, (%A1) */'
 },
 
 # other operations
@@ -438,7 +439,7 @@ $comment_string = '/*';
   "attr"      => "const char *label",
   "init_attr" => '  attr->symconst_label = label;',
   "reg_req"   => { "out" => [ "gp" ] },
-#  "emit"      => '. LDR %D1, %C /* Mov Const into register */',
+#  "emit"      => '. ldr %D1, %C /* Mov Const into register */',
   "cmp_attr"  =>
 '  /* should be identical but ...*/
    return strcmp(attr_a->symconst_label, attr_b->symconst_label);'
@@ -466,8 +467,7 @@ $comment_string = '/*';
   "state"     => "exc_pinned",
   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
-  "emit"      => '. LDR %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
-#  "emit"      => '. LDR %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */',
+  "emit"      => '. ldr %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
   "outs"      => [ "res", "M" ],
 },
 
@@ -477,8 +477,7 @@ $comment_string = '/*';
   "state"     => "exc_pinned",
   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
-  "emit"      => '. LDRB %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
-#  "emit"      => '. LDRB %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */',
+  "emit"      => '. ldrb %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
   "outs"      => [ "res", "M" ],
 },
 
@@ -488,8 +487,7 @@ $comment_string = '/*';
   "state"     => "exc_pinned",
   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
-  "emit"      => '. LDRSB %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
-#  "emit"      => '. LDRSB %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */',
+  "emit"      => '. ldrsb %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
   "outs"      => [ "res", "M" ],
 },
 
@@ -499,8 +497,7 @@ $comment_string = '/*';
   "state"     => "exc_pinned",
   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
-  "emit"      => '. LDRH %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
-#  "emit"      => '. LDRH %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */',
+  "emit"      => '. ldrh %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
   "outs"      => [ "res", "M" ],
 },
 
@@ -510,8 +507,7 @@ $comment_string = '/*';
   "state"     => "exc_pinned",
   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
   "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
-  "emit"      => '. LDRSH %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
-#  "emit"      => '. LDRSH %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */',
+  "emit"      => '. ldrsh %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */',
   "outs"      => [ "res", "M" ],
 },
 
@@ -521,8 +517,7 @@ $comment_string = '/*';
   "state"     => "exc_pinned",
   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
-  "emit"      => '. STRB %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
-#  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */',
+  "emit"      => '. strb %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
   "outs"      => [ "M" ],
 },
 
@@ -532,8 +527,7 @@ $comment_string = '/*';
   "state"     => "exc_pinned",
   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
-  "emit"      => '. STRSB %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
-#  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */',
+  "emit"      => '. strsb %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
   "outs"      => [ "M" ],
 },
 
@@ -543,8 +537,7 @@ $comment_string = '/*';
   "state"     => "exc_pinned",
   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
-  "emit"      => '. STRH %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
-#  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */',
+  "emit"      => '. strh %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
   "outs"      => [ "M" ],
 },
 
@@ -554,8 +547,7 @@ $comment_string = '/*';
   "state"     => "exc_pinned",
   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
-  "emit"      => '. STRSH%S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
-#  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */',
+  "emit"      => '. strsh%S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
   "outs"      => [ "M" ],
 },
 
@@ -565,8 +557,7 @@ $comment_string = '/*';
   "state"     => "exc_pinned",
   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
   "reg_req"   => { "in" => [ "gp", "gp", "none" ] },
-  "emit"      => '. STR %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
-#  "emit"      => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */',
+  "emit"      => '. str %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */',
   "outs"      => [ "M" ],
 },
 
@@ -576,7 +567,7 @@ $comment_string = '/*';
   "state"     => "exc_pinned",
   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
   "reg_req"   => { "in" => [ "sp", "gp", "gp", "gp", "gp", "none" ], "out" => [ "gp", "none" ] },
-  "emit"      => '. STMFD %S1!, {%S2, %S3, %S4, %S5} /* Store multiple on Stack*/',
+  "emit"      => '. stmfd %S1!, {%S2, %S3, %S4, %S5} /* Store multiple on Stack*/',
   "outs"      => [ "ptr", "M" ],
 },
 
@@ -586,136 +577,195 @@ $comment_string = '/*';
   "state"     => "exc_pinned",
   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
   "reg_req"   => { "in" => [ "sp", "none" ], "out" => [ "gp", "gp", "gp", "none" ] },
-  "emit"      => '. LDMFD %S1, {%D1, %D2, %D3} /* Load multiple from Stack */',
+  "emit"      => '. ldmfd %S1, {%D1, %D2, %D3} /* Load multiple from Stack */',
   "outs"      => [ "res0", "res1", "res2", "M" ],
 },
 
 
-
-
-
-
-
-
-#--------------------------------------------------------#
-#    __ _             _                     _            #
-#   / _| |           | |                   | |           #
-#  | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
-#  |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
-#  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
-#  |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
-#--------------------------------------------------------#
+#---------------------------------------------------#
+#    __                               _             #
+#   / _|                             | |            #
+#  | |_ _ __   __ _   _ __   ___   __| | ___  ___   #
+#  |  _| '_ \ / _` | | '_ \ / _ \ / _` |/ _ \/ __|  #
+#  | | | |_) | (_| | | | | | (_) | (_| |  __/\__ \  #
+#  |_| | .__/ \__,_| |_| |_|\___/ \__,_|\___||___/  #
+#      | |                                          #
+#      |_|                                          #
+#---------------------------------------------------#
 
 # commutative operations
 
-"fAdd" => {
+"fpaAdd" => {
   "op_flags"  => "C",
   "irn_flags" => "R",
-  "comment"   => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
-  "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
-  "emit"      => '. FADD%Mx %D1, %S1, %S2 /* FP Add(%S1, %S2) -> %D1 */',
+  "comment"   => "construct FPA Add: Add(a, b) = Add(b, a) = a + b",
+  "reg_req"   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  "emit"      => '. adf%M %D1, %S1, %S2 /* FPA Add(%S1, %S2) -> %D1 */',
 },
 
-"fMul" => {
+"fpaMul" => {
   "op_flags"  => "C",
-  "comment"   => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
-  "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
-  "emit"      =>'. FMUL%Mx %D1, %S1, %S2 /* FP Mul(%S1, %S2) -> %D1 */',
+  "comment"   => "construct FPA Mul: Mul(a, b) = Mul(b, a) = a * b",
+  "reg_req"   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  "emit"      =>'. muf%M %D1, %S1, %S2 /* FPA Mul(%S1, %S2) -> %D1 */',
 },
 
-"fDiv" => {
-  "comment"   => "construct FP Div: Div(a, b) = a / b",
-  "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
-  "emit"      =>'. FDIV%Mx %D1, %S1, %S2 /* FP Div(%S1, %S2) -> %D1 */',
+"fpaFMul" => {
+  "op_flags"  => "C",
+  "comment"   => "construct FPA Fast Mul: Mul(a, b) = Mul(b, a) = a * b",
+  "reg_req"   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  "emit"      =>'. fml%M %D1, %S1, %S2 /* FPA Fast Mul(%S1, %S2) -> %D1 */',
 },
 
-"fMax" => {
+"fpaMax" => {
   "op_flags"  => "C",
   "irn_flags" => "R",
-  "comment"   => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b",
-  "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
-  "emit"      =>'. fmax %S1, %S2, %D1 /* FP Max(%S1, %S2) -> %D1 */',
+  "comment"   => "construct FPA Max: Max(a, b) = Max(b, a) = a > b ? a : b",
+  "reg_req"   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  "emit"      =>'. fmax %S1, %S2, %D1 /* FPA Max(%S1, %S2) -> %D1 */',
 },
 
-"fMin" => {
+"fpaMin" => {
   "op_flags"  => "C",
   "irn_flags" => "R",
-  "comment"   => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b",
-  "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
-  "emit"      =>'. fmin %S1, %S2, %D1 /* FP Min(%S1, %S2) -> %D1 */',
+  "comment"   => "construct FPA Min: Min(a, b) = Min(b, a) = a < b ? a : b",
+  "reg_req"   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  "emit"      =>'. fmin %S1, %S2, %D1 /* FPA Min(%S1, %S2) -> %D1 */',
 },
 
 # not commutative operations
 
-"fSub" => {
+"fpaSub" => {
+  "irn_flags" => "R",
+  "comment"   => "construct FPA Sub: Sub(a, b) = a - b",
+  "reg_req"   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  "emit"      => '. suf%M %D1, %S1, %S2 /* FPA Sub(%S1, %S2) -> %D1 */'
+},
+
+"fpaRsb" => {
+  "irn_flags" => "R",
+  "comment"   => "construct FPA reverse Sub: Sub(a, b) = b - a",
+  "reg_req"   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  "emit"      => '. rsf%M %D1, %S1, %S2 /* FPA reverse Sub(%S1, %S2) -> %D1 */'
+},
+
+"fpaDiv" => {
+  "comment"   => "construct FPA Div: Div(a, b) = a / b",
+  "reg_req"   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  "emit"      =>'. dvf%M %D1, %S1, %S2 /* FPA Div(%S1, %S2) -> %D1 */',
+},
+
+"fpaRdv" => {
+  "comment"   => "construct FPA reverse Div: Div(a, b) = b / a",
+  "reg_req"   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  "emit"      =>'. rdf%M %D1, %S1, %S2 /* FPA reverse Div(%S1, %S2) -> %D1 */',
+},
+
+"fpaFDiv" => {
+  "comment"   => "construct FPA Fast Div: Div(a, b) = a / b",
+  "reg_req"   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  "emit"      =>'. fdv%M %D1, %S1, %S2 /* FPA Fast Div(%S1, %S2) -> %D1 */',
+},
+
+"fpaFRdv" => {
+  "comment"   => "construct FPA Fast reverse Div: Div(a, b) = b / a",
+  "reg_req"   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  "emit"      =>'. frd%M %D1, %S1, %S2 /* FPA Fast reverse Div(%S1, %S2) -> %D1 */',
+},
+
+"fpaMov" => {
   "irn_flags" => "R",
-  "comment"   => "construct FP Sub: Sub(a, b) = a - b",
-  "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
-  "emit"      => '. FSUB%Mx %D1, %S1, %S2 /* FP Sub(%S1, %S2) -> %D1 */'
+  "comment"   => "construct FPA Move: b = a",
+  "reg_req"   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
+  "emit"      => '. mvf%M %S1, %D1 /* FPA Mov %S1 -> %D1 */',
 },
 
-"fNeg" => {
+"fpaMnv" => {
   "irn_flags" => "R",
-  "comment"   => "construct FP Neg: Neg(a) = -a",
-  "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
-  "emit"      => '. fneg %S1, %D1 /* FP Neg(%S1) -> %D1 */',
+  "comment"   => "construct FPA Move Negated: b = -a",
+  "reg_req"   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
+  "emit"      => '. mnf%M %S1, %D1 /* FPA Neg(%S1) -> %D1 */',
 },
 
-"fAbs" => {
+"fpaAbs" => {
   "irn_flags" => "R",
-  "comment"   => "construct FP Absolute value: fAbsd(a) = |a|",
-  "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
-  "emit"      => '. FABS%Mx %D1, %S1 /* FP Absd(%S1) -> %D1 */',
+  "comment"   => "construct FPA Absolute value: fAbsd(a) = |a|",
+  "reg_req"   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
+  "emit"      => '. abs%M %D1, %S1 /* FPA Abs(%S1) -> %D1 */',
 },
 
 # other operations
 
-"fConst" => {
+"fpaConst" => {
   "op_flags"  => "c",
   "irn_flags" => "R",
-  "comment"   => "represents a FP constant",
+  "comment"   => "represents a FPA constant",
   "attr"      => "tarval *val",
   "init_attr" => 'attr->value = val;',
-  "reg_req"   => { "out" => [ "fp" ] },
-  "emit"      => '. FMOV %D1, %C /* Mov fConst into register */',
+  "reg_req"   => { "out" => [ "fpa" ] },
+  "emit"      => '. fmov %D1, %C /* Mov fConst into register */',
   "cmp_attr"  => 'return attr_a->value != attr_b->value;',
 },
 
-"fConvD2S" => {
+"fpaFlt" => {
   "irn_flags" => "R",
-  "comment"   => "convert double to single",
-  "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
-  "emit"      => '. FCVTSD %D1, %S1 /* Convert double to single */',
+  "comment"   => "construct a FPA integer->float conversion",
+  "reg_req"   => { "in" => ["gp"], "out" => [ "fpa" ] },
+  "emit"      => '. flt%M %D1, %S1 /* convert int to fp */',
 },
 
-"fConvS2D" => {
+"fpaFix" => {
   "irn_flags" => "R",
-  "comment"   => "convert single to double",
-  "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
-  "emit"      => '. FCVTDS %D1, %S1 /* Convert single to double */',
+  "comment"   => "construct a FPA float->integer conversion",
+  "reg_req"   => { "in" => ["fpa"], "out" => [ "gp" ] },
+  "emit"      => '. fix %D1, %S1 /* convert fp to int */',
 },
 
-
 # Load / Store
 
-"fLoad" => {
+"fpaLdf" => {
   "op_flags"  => "L|F",
   "irn_flags" => "R",
   "state"     => "exc_pinned",
-  "comment"   => "construct FP Load: Load(ptr, mem) = LD ptr",
-  "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "fp", "none" ] },
-  "emit"      => '. FLD%Mx %D1, %S1 /* Load((%S1)) -> %D1 */',
+  "comment"   => "construct FPA Load: Load(ptr, mem) = LD ptr",
+  "attr"      => "ir_mode *op_mode",
+  "init_attr" => "attr->op_mode = op_mode;",
+  "reg_req"   => { "in" => [ "gp", "none" ], "out" => [ "fpa", "none" ] },
+  "emit"      => '. ldf%M %D1, [%S1, #0] /* Load((%S1)) -> %D1 */',
   "outs"      => [ "res", "M" ],
 },
 
-"fStore" => {
+"fpaStf" => {
   "op_flags"  => "L|F",
   "irn_flags" => "R",
   "state"     => "exc_pinned",
   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
-  "reg_req"   => { "in" => [ "gp", "fp", "none" ] },
-  "emit"      => '. FST%Mx %S2, %S1 /* Store(%S2) -> (%S1), (%A1, %A2) */',
+  "attr"      => "ir_mode *op_mode",
+  "init_attr" => "attr->op_mode = op_mode;",
+  "reg_req"   => { "in" => [ "gp", "fpa", "none" ] },
+  "emit"      => '. stf%M [%S2, #0], %S1 /* Store(%S2) -> (%S1), (%A1, %A2) */',
   "outs"      => [ "M" ],
 },
 
+"fpaDbl2GP" => {
+  "op_flags"  => "L|F",
+  "irn_flags" => "R",
+  "state"     => "exc_pinned",
+  "comment"   => "construct fp double to 2 gp register transfer",
+  "reg_req"   => { "in" => [ "fpa", "none" ], "out" => [ "gp", "gp" ] },
+  "outs"      => [ "low", "high", "M" ],
+},
+
+
+#---------------------------------------------------#
+#          __                         _             #
+#         / _|                       | |            #
+#  __   _| |_ _ __    _ __   ___   __| | ___  ___   #
+#  \ \ / /  _| '_ \  | '_ \ / _ \ / _` |/ _ \/ __|  #
+#   \ V /| | | |_) | | | | | (_) | (_| |  __/\__ \  #
+#    \_/ |_| | .__/  |_| |_|\___/ \__,_|\___||___/  #
+#            | |                                    #
+#            |_|                                    #
+#---------------------------------------------------#
+
 ); # end of %nodes
index e665bb4..02cc859 100644 (file)
@@ -1,4 +1,4 @@
-/* The codegenrator (transform FIRM into arm FIRM */
+/* The codegenerator (transform FIRM into arm FIRM */
 /* $Id$ */
 
 #ifdef HAVE_CONFIG_H
@@ -182,24 +182,25 @@ static ir_node *create_const_graph(ir_node *irn, ir_node *block) {
 }
 
 
-
+/**
+ * Creates code for a Firm Const node.
+ */
 static ir_node *gen_Const(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *result;
        ir_graph *irg = current_ir_graph;
        ir_node *block = get_nodes_block(irn);
        ir_mode *mode = get_irn_mode(irn);
        dbg_info *dbg = get_irn_dbg_info(irn);
 
-       assert(mode != mode_E && "IEEE Extended FP not supported");
-       if (mode == mode_F)
-               result = new_rd_arm_fConst(dbg, irg, block, mode, get_Const_tarval(irn));
-       else if (mode == mode_D)
-               result = new_rd_arm_fConst(dbg, irg, block, mode, get_Const_tarval(irn));
-       else if (mode == mode_P)
+       if (mode_is_float(mode)) {
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaConst(dbg, irg, block, mode, get_Const_tarval(irn));
+               else if (USE_VFP(cg->isa))
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               assert(0 && "NYI");
+       }
+       else if (mode_is_reference(mode))
                return irn;
-       else
-               result = create_const_graph(irn, block);
-       return result;
+       return create_const_graph(irn, block);
 }
 
 static ir_node *gen_mask(ir_node *irn, ir_node *op, int result_bits) {
@@ -235,21 +236,34 @@ static ir_node *gen_Conv(ir_node *irn, arm_code_gen_t *cg) {
        ir_mode *out_mode = get_irn_mode(irn);
        dbg_info *dbg    = get_irn_dbg_info(irn);
 
-       assert( in_mode != mode_E && "");
-       assert( in_mode != mode_Ls && "");
-       assert( in_mode != mode_Lu && "");
-       assert( out_mode != mode_E && "");
-       assert( out_mode != mode_Ls && "");
-       assert( out_mode != mode_Lu && "");
-
        if (in_mode == out_mode)
                return op;
 
-       if ((mode_is_int(in_mode) || mode_is_reference(in_mode))
-               && (mode_is_reference(out_mode) || mode_is_int(out_mode))) {
-               int in_bits = get_mode_size_bits(in_mode);
+       if (mode_is_float(in_mode) || mode_is_float(out_mode)) {
+               cg->have_fp = 1;
+
+               if (USE_FPA(cg->isa)) {
+                       if (mode_is_float(in_mode)) {
+                               if (mode_is_float(out_mode)) {
+                                       /* from float to float */
+                                       return new_rd_arm_fpaMov(dbg, irg, block, op, out_mode);
+                               }
+                               else {
+                                       /* from float to int */
+                                       return new_rd_arm_fpaFix(dbg, irg, block, op, out_mode);
+                               }
+                       }
+                       else {
+                               /* from int to float */
+                               return new_rd_arm_fpaFlt(dbg, irg, block, op, out_mode);
+                       }
+               }
+               assert(0 && "NYI");
+       }
+       else { /* complete in gp registers */
+               int in_bits  = get_mode_size_bits(in_mode);
                int out_bits = get_mode_size_bits(out_mode);
-               int in_sign = get_mode_sign(in_mode);
+               int in_sign  = get_mode_sign(in_mode);
                int out_sign = get_mode_sign(out_mode);
 
                // 32 -> 32
@@ -309,20 +323,8 @@ static ir_node *gen_Conv(ir_node *irn, arm_code_gen_t *cg) {
                }
                assert(0 && "recheck integer conversion logic!");
                return irn;
-       } else if (in_mode == mode_D && out_mode == mode_F) {
-               return new_rd_arm_fConvD2S(dbg, irg, block, op, out_mode);
-       } else if (in_mode == mode_F && out_mode == mode_D) {
-               return new_rd_arm_fConvS2D(dbg, irg, block, op, out_mode);
-       } else if (mode_is_int(in_mode) && mode_is_float(out_mode)) {
-               cg->have_fp = 1;
-               return irn; /* TODO: implement int->float conversion*/
-       } else if (mode_is_float(in_mode) && mode_is_int(out_mode)) {
-               cg->have_fp = 1;
-               return irn; /* TODO: implement float->int conversion*/
-       } else {
-               assert(0 && "not implemented conversion");
-               return irn;
        }
+       return NULL;
 }
 
 /**
@@ -360,11 +362,14 @@ static ir_node *gen_Add(ir_node *irn, arm_code_gen_t *cg) {
        arm_shift_modifier mod;
        dbg_info *dbg = get_irn_dbg_info(irn);
 
-       assert(mode != mode_E && "IEEE Extended FP not supported");
-
        if (mode_is_float(mode)) {
                cg->have_fp = 1;
-               return new_rd_arm_fAdd(dbg, irg, block, op1, op2, mode);
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaAdd(dbg, irg, block, op1, op2, mode);
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        if (mode_is_numP(mode)) {
                if (is_arm_Mov_i(op1))
@@ -423,11 +428,14 @@ static ir_node *gen_Mul(ir_node *irn, arm_code_gen_t *cg) {
        ir_graph *irg = current_ir_graph;
        dbg_info *dbg = get_irn_dbg_info(irn);
 
-       assert(mode != mode_E && "IEEE Extended FP not supported");
-
        if (mode_is_float(mode)) {
                cg->have_fp = 1;
-               return new_rd_arm_fMul(dbg, irg, block, op1, op2, mode);
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaMul(dbg, irg, block, op1, op2, mode);
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        return new_rd_arm_Mul(dbg, irg, block, op1, op2, mode);
 }
@@ -447,7 +455,15 @@ static ir_node *gen_Quot(ir_node *irn, arm_code_gen_t *cg) {
 
        assert(mode != mode_E && "IEEE Extended FP not supported");
 
-       return new_rd_arm_fDiv(dbg, current_ir_graph, block, op1, op2, mode);
+       cg->have_fp = 1;
+       if (USE_FPA(cg->isa))
+               return new_rd_arm_fpaDiv(dbg, current_ir_graph, block, op1, op2, mode);
+       else if (USE_VFP(cg->isa)) {
+               assert(mode != mode_E && "IEEE Extended FP not supported");
+       }
+       assert(0 && "NYI");
+
+       return NULL;
 }
 
 #define GEN_INT_OP(op) \
@@ -525,11 +541,14 @@ static ir_node *gen_Sub(ir_node *irn, arm_code_gen_t *cg) {
        ir_graph *irg = current_ir_graph;
        dbg_info *dbg = get_irn_dbg_info(irn);
 
-       assert(mode != mode_E && "IEEE Extended FP not supported");
-
        if (mode_is_float(mode)) {
                cg->have_fp = 1;
-               return new_rd_arm_fSub(dbg, irg, block, op1, op2, mode);
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaSub(dbg, irg, block, op1, op2, mode);
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        if (mode_is_numP(mode)) {
                if (is_arm_Mov_i(op1))
@@ -658,11 +677,14 @@ static ir_node *gen_Abs(ir_node *irn, arm_code_gen_t *cg) {
        ir_mode *mode = get_irn_mode(irn);
        dbg_info *dbg = get_irn_dbg_info(irn);
 
-       assert(mode != mode_E && "IEEE Extended FP not supported");
-
        if (mode_is_float(mode)) {
                cg->have_fp = 1;
-               return new_rd_arm_fAbs(dbg, current_ir_graph, block, op, mode);
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaAbs(dbg, current_ir_graph, block, op, mode);
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        return new_rd_arm_Abs(dbg, current_ir_graph, block, op, mode);
 }
@@ -681,7 +703,13 @@ static ir_node *gen_Minus(ir_node *irn, arm_code_gen_t *cg) {
        dbg_info *dbg = get_irn_dbg_info(irn);
 
        if (mode_is_float(mode)) {
-               return new_rd_arm_fNeg(dbg, irg, block, op, mode);
+               cg->have_fp = 1;
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaMnv(dbg, irg, block, op, mode);
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        return new_rd_arm_Rsb_i(dbg, irg, block, op, mode, get_mode_null(mode));
 }
@@ -703,8 +731,13 @@ static ir_node *gen_Load(ir_node *irn, arm_code_gen_t *cg) {
 
        if (mode_is_float(mode)) {
                cg->have_fp = 1;
-               /* FIXME: set the load mode */
-               return new_rd_arm_fLoad(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaLdf(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn),
+                               get_Load_mode(irn));
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        if (mode == mode_Bu) {
                return new_rd_arm_Loadb(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
@@ -742,8 +775,13 @@ static ir_node *gen_Store(ir_node *irn, arm_code_gen_t *cg) {
        assert(mode != mode_E && "IEEE Extended FP not supported");
        if (mode_is_float(mode)) {
                cg->have_fp = 1;
-               /* FIXME: set the store mode */
-               return new_rd_arm_fStore(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
+               if (USE_FPA(cg->isa))
+                       return new_rd_arm_fpaStf(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn),
+                               get_Store_mem(irn), get_irn_mode(get_Store_value(irn)));
+               else if (USE_VFP(cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+               }
+               assert(0 && "NYI");
        }
        if (mode == mode_Bu) {
                return new_rd_arm_Storeb(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
@@ -1082,9 +1120,9 @@ static ir_node *gen_FrameStore(ir_node *irn, arm_code_gen_t *cg) {
  *
  *********************************************************/
 
-/************************************************************************/
-/* move constants out of startblock                                       */
-/************************************************************************/
+/**
+ * move constants out of the start block
+ */
 void arm_move_consts(ir_node *node, void *env) {
        arm_code_gen_t *cgenv = (arm_code_gen_t *)env;
        int i;
@@ -1093,14 +1131,18 @@ void arm_move_consts(ir_node *node, void *env) {
                return;
 
        if (is_Phi(node)) {
-               for (i = 0; i < get_irn_arity(node); i++) {
+               for (i = get_irn_arity(node) - 1; i >= 0; --i) {
                        ir_node *pred = get_irn_n(node,i);
                        opcode pred_code = get_irn_opcode(pred);
                        if (pred_code == iro_Const) {
                                ir_node *const_graph;
                                const_graph = create_const_graph(pred, get_nodes_block(get_irn_n(get_nodes_block(node),i)));
                                set_irn_n(node, i, const_graph);
-                       } else if (pred_code == iro_SymConst) {
+                       }
+                       else if (pred_code == iro_SymConst) {
+                               /* FIXME: in general, SymConst always require a load, so it
+                                  might be better to place them into the first real block
+                                  and let the spiller rematerialize them. */
                                const char *str = get_sc_name(pred);
                                ir_node *symconst_node;
                                symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
index f42a52b..4345c46 100644 (file)
@@ -5,6 +5,11 @@
 #include "config.h"
 #endif
 
+#ifdef WITH_LIBCORE
+#include <libcore/lc_opts.h>
+#include <libcore/lc_opts_enum.h>
+#endif /* WITH_LIBCORE */
+
 #include "pseudo_irg.h"
 #include "irgwalk.h"
 #include "irprog.h"
@@ -122,7 +127,7 @@ static const arch_register_req_t *arm_get_irn_reg_req(const void *self, arch_reg
                        DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
 
                        if (mode_is_float(mode)) {
-                               memcpy(req, &(arm_default_req_arm_fp.req), sizeof(*req));
+                               memcpy(req, &(arm_default_req_arm_fpa.req), sizeof(*req));
                        }
                        else if (mode_is_int(mode) || mode_is_reference(mode)) {
                                memcpy(req, &(arm_default_req_arm_gp.req), sizeof(*req));
@@ -324,20 +329,84 @@ static void arm_emit_and_done(void *self) {
        free(self);
 }
 
-enum convert_which { low, high };
+/**
+ * Move a double floating point value into an integer register.
+ * Place the move operation into block bl.
+ *
+ * Handle some special cases here:
+ * 1.) A constant: simply split into two
+ * 2.) A load: siply split into two
+ */
+static ir_node *convert_dbl_to_int(ir_node *bl, ir_node *arg, ir_node *mem,
+                                   ir_node **resH, ir_node **resL) {
+       if (is_Const(arg)) {
+               tarval *tv = get_Const_tarval(arg);
+               unsigned v;
+
+               /* get the upper 32 bits */
+               v =            get_tarval_sub_bits(tv, 7);
+               v = (v << 8) | get_tarval_sub_bits(tv, 6);
+               v = (v << 8) | get_tarval_sub_bits(tv, 5);
+               v = (v << 8) | get_tarval_sub_bits(tv, 4);
+               *resH = new_Const_long(mode_Is, v);
+
+               /* get the lower 32 bits */
+               v =            get_tarval_sub_bits(tv, 3);
+               v = (v << 8) | get_tarval_sub_bits(tv, 2);
+               v = (v << 8) | get_tarval_sub_bits(tv, 1);
+               v = (v << 8) | get_tarval_sub_bits(tv, 0);
+               *resL = new_Const_long(mode_Is, v);
+       }
+       else if (get_irn_op(skip_Proj(arg)) == op_Load) {
+               /* FIXME: handling of low/high depends on LE/BE here */
+               assert(0);
+       }
+       else {
+               ir_graph *irg = current_ir_graph;
+               ir_node *conv;
+
+               conv = new_rd_arm_fpaDbl2GP(NULL, irg, bl, arg, mem);
+               /* move high/low */
+               *resL = new_r_Proj(irg, bl, conv, mode_Is, pn_arm_fpaDbl2GP_low);
+               *resH = new_r_Proj(irg, bl, conv, mode_Is, pn_arm_fpaDbl2GP_high);
+               mem   = new_r_Proj(irg, bl, conv, mode_M,  pn_arm_fpaDbl2GP_M);
+       }
+       return mem;
+}
 
 /**
- * Move an floating point value to a integer register.
+ * Move a single floating point value into an integer register.
  * Place the move operation into block bl.
+ *
+ * Handle some special cases here:
+ * 1.) A constant: simply move
+ * 2.) A load: siply load
  */
-static ir_node *convert_to_int(ir_node *bl, ir_node *arg, enum convert_which which) {
+static ir_node *convert_sng_to_int(ir_node *bl, ir_node *arg) {
+       if (is_Const(arg)) {
+               tarval *tv = get_Const_tarval(arg);
+               unsigned v;
+
+               /* get the lower 32 bits */
+               v =            get_tarval_sub_bits(tv, 3);
+               v = (v << 8) | get_tarval_sub_bits(tv, 2);
+               v = (v << 8) | get_tarval_sub_bits(tv, 1);
+               v = (v << 8) | get_tarval_sub_bits(tv, 0);
+               return new_Const_long(mode_Is, v);
+       }
+       else if (get_irn_op(skip_Proj(arg)) == op_Load) {
+               ir_node *load;
+
+               load = skip_Proj(arg);
+       }
+       assert(0);
        return NULL;
 }
 
 /**
  * Convert the arguments of a call to support the
  * ARM calling convention of general purpose AND floating
- * point arguments
+ * point arguments.
  */
 static void handle_calls(ir_node *call, void *env)
 {
@@ -373,18 +442,20 @@ static void handle_calls(ir_node *call, void *env)
 
                        if (mode_is_float(mode)) {
                                if (get_mode_size_bits(mode) > 32) {
+                                       ir_node *mem = get_Call_mem(call);
+
+                                       /* Beware: ARM wants the high part first */
                                        size += 2 * 4;
-                                       new_tp[idx] = cg->int_tp;
-                                       new_in[idx] = convert_to_int(bl, get_Call_param(call, i), low);
-                                       ++idx;
-                                       new_tp[idx] = cg->int_tp;
-                                       new_in[idx] = convert_to_int(bl, get_Call_param(call, i), high);
-                                       ++idx;
+                                       new_tp[idx]   = cg->int_tp;
+                                       new_tp[idx+1] = cg->int_tp;
+                                       mem = convert_dbl_to_int(bl, get_Call_param(call, i), mem, &new_in[idx], &new_in[idx+1]);
+                                       idx += 2;
+                                       set_Call_mem(call, mem);
                                }
                                else {
                                        size += 4;
                                        new_tp[idx] = cg->int_tp;
-                                       new_in[idx] = convert_to_int(bl, get_Call_param(call, i), low);
+                                       new_in[idx] = convert_sng_to_int(bl, get_Call_param(call, i));
                                        ++idx;
                                }
                                flag = 1;
@@ -443,7 +514,7 @@ static void handle_calls(ir_node *call, void *env)
 }
 
 /**
- * Handle graph transformations before the abi converter does it's work
+ * Handle graph transformations before the abi converter does its work.
  */
 static void arm_before_abi(void *self) {
        arm_code_gen_t *cg = self;
@@ -459,7 +530,7 @@ static const arch_code_generator_if_t arm_code_gen_if = {
        arm_prepare_graph,
        arm_before_sched,   /* before scheduling hook */
        arm_before_ra,      /* before register allocation hook */
-       NULL, /* after register allocation */
+       NULL,               /* after register allocation */
        arm_emit_and_done,
 };
 
@@ -641,6 +712,7 @@ static arm_isa_t arm_isa_template = {
        0,                     /* use generic register names instead of SP, LR, PC */
        NULL,                  /* current code generator */
        NULL,                  /* output file */
+       ARM_FPU_ARCH_FPE,      /* FPU architecture */
 };
 
 /**
@@ -702,7 +774,7 @@ static int arm_get_n_reg_class(const void *self) {
  * Return the register class with requested index.
  */
 static const arch_register_class_t *arm_get_reg_class(const void *self, int i) {
-       return i == 0 ? &arm_reg_classes[CLASS_arm_gp] : &arm_reg_classes[CLASS_arm_fp];
+       return i == 0 ? &arm_reg_classes[CLASS_arm_gp] : &arm_reg_classes[CLASS_arm_fpa];
 }
 
 /**
@@ -713,7 +785,7 @@ static const arch_register_class_t *arm_get_reg_class(const void *self, int i) {
  */
 const arch_register_class_t *arm_get_reg_class_for_mode(const void *self, const ir_mode *mode) {
        if (mode_is_float(mode))
-               return &arm_reg_classes[CLASS_arm_fp];
+               return &arm_reg_classes[CLASS_arm_fpa];
        else
                return &arm_reg_classes[CLASS_arm_gp];
 }
@@ -766,7 +838,7 @@ static void *arm_abi_init(const be_abi_call_t *call, const arch_env_t *arch_env,
 static void arm_abi_dont_save_regs(void *self, pset *s)
 {
        arm_abi_env_t *env = self;
-       if(env->flags.try_omit_fp)
+       if (env->flags.try_omit_fp)
                pset_insert_ptr(s, env->isa->bp);
 }
 
@@ -941,7 +1013,7 @@ void arm_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi
                mode = get_type_mode(tp);
 
                be_abi_call_res_reg(abi, 0,
-                       mode_is_float(mode) ? &arm_fp_regs[REG_F0] : &arm_gp_regs[REG_R0]);
+                       mode_is_float(mode) ? &arm_fpa_regs[REG_F0] : &arm_gp_regs[REG_R0]);
        }
 }
 
@@ -988,7 +1060,24 @@ static int arm_get_reg_class_alignment(const void *self, const arch_register_cla
 }
 
 #ifdef WITH_LIBCORE
+
+/* fpu set architectures. */
+static const lc_opt_enum_int_items_t arm_fpu_items[] = {
+       { "softfloat", ARM_FPU_ARCH_SOFTFLOAT },
+       { "fpe",       ARM_FPU_ARCH_FPE },
+       { "fpa",       ARM_FPU_ARCH_FPA },
+       { "vfp1xd",    ARM_FPU_ARCH_VFP_V1xD },
+       { "vfp1",      ARM_FPU_ARCH_VFP_V1 },
+       { "vfp2",      ARM_FPU_ARCH_VFP_V2 },
+       { NULL,        0 }
+};
+
+static lc_opt_enum_int_var_t arch_fpu_var = {
+       &arm_isa_template.fpu_arch, arm_fpu_items
+};
+
 static const lc_opt_table_entry_t arm_options[] = {
+       LC_OPT_ENT_ENUM_INT("fpunit",    "select the floating point unit", &arch_fpu_var),
        LC_OPT_ENT_BOOL("gen_reg_names", "use generic register names", &arm_isa_template.gen_reg_names),
        { NULL }
 };
@@ -998,6 +1087,7 @@ static const lc_opt_table_entry_t arm_options[] = {
  *
  * Options so far:
  *
+ * arm-fpuunit=unit     select the floating point unit
  * arm-gen_reg_names    use generic register names instead of SP, LR, PC
  */
 static void arm_register_options(lc_opt_entry_t *ent)
index 01f781c..7091dea 100644 (file)
 
 typedef struct _arm_isa_t arm_isa_t;
 
+/** The following bitmasks control CPU extensions:  */
+enum arm_cpu_extensions {
+       ARM_EXT_V1    = 0x00000001,  /**< All processors (core set). */
+       ARM_EXT_V2    = 0x00000002,  /**< Multiply instructions. */
+       ARM_EXT_V2S   = 0x00000004,  /**< SWP instructions. */
+       ARM_EXT_V3    = 0x00000008,  /**< MSR MRS. */
+       ARM_EXT_V3M   = 0x00000010,  /**< Allow long multiplies. */
+       ARM_EXT_V4    = 0x00000020,  /**< Allow half word loads. */
+       ARM_EXT_V4T   = 0x00000040,  /**< Thumb v1. */
+       ARM_EXT_V5    = 0x00000080,  /**< Allow CLZ, etc. */
+       ARM_EXT_V5T   = 0x00000100,  /**< Thumb v2.ยด*/
+       ARM_EXT_V5ExP = 0x00000200,  /**< DSP core set. */
+       ARM_EXT_V5E   = 0x00000400,  /**< DSP Double transfers. */
+       ARM_EXT_V5J   = 0x00000800,  /**< Jazelle extension.   */
+
+       /* Co-processor space extensions.  */
+       ARM_CEXT_XSCALE   = 0x00800000, /**< Allow MIA etc. */
+       ARM_CEXT_MAVERICK = 0x00400000, /**< Use Cirrus/DSP coprocessor. */
+       ARM_CEXT_IWMMXT   = 0x00200000, /**< Intel Wireless MMX technology coprocessor. */
+};
+
+/**
+ * Architectures are the sum of the base and extensions.  The ARM ARM (rev E)
+ * defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
+ * ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE.  To these we add
+ * three more to cover cores prior to ARM6.  Finally, there are cores which
+ * implement further extensions in the co-processor space.
+ */
+enum arm_architectiures {
+       ARM_ARCH_V1     = ARM_EXT_V1,
+       ARM_ARCH_V2     = ARM_ARCH_V1 | ARM_EXT_V2,
+       ARM_ARCH_V2S    = ARM_ARCH_V2 | ARM_EXT_V2S,
+       ARM_ARCH_V3     = ARM_ARCH_V2S | ARM_EXT_V3,
+       ARM_ARCH_V3M    = ARM_ARCH_V3 | ARM_EXT_V3M,
+       ARM_ARCH_V4xM   = ARM_ARCH_V3 | ARM_EXT_V4,
+       ARM_ARCH_V4     = ARM_ARCH_V3M | ARM_EXT_V4,
+       ARM_ARCH_V4TxM  = ARM_ARCH_V4xM | ARM_EXT_V4T,
+       ARM_ARCH_V4T    = ARM_ARCH_V4 | ARM_EXT_V4T,
+       ARM_ARCH_V5xM   = ARM_ARCH_V4xM| ARM_EXT_V5,
+       ARM_ARCH_V5     = ARM_ARCH_V4 | ARM_EXT_V5,
+       ARM_ARCH_V5TxM  = ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T,
+       ARM_ARCH_V5T    = ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T,
+       ARM_ARCH_V5TExP = ARM_ARCH_V5T | ARM_EXT_V5ExP,
+       ARM_ARCH_V5TE   = ARM_ARCH_V5TExP | ARM_EXT_V5E,
+       ARM_ARCH_V5TEJ  = ARM_ARCH_V5TE | ARM_EXT_V5J,
+
+       /* Processors with specific extensions in the co-processor space.  */
+       ARM_ARCH_XSCALE = ARM_ARCH_V5TE | ARM_CEXT_XSCALE,
+       ARM_ARCH_IWMMXT = ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT,
+
+       ARM_ARCH_MASK   = 0x00ffffff,
+};
+
+/** Floating point instruction set. */
+enum arm_fp_architectures {
+       ARM_FPU_FPA_EXT_V1     = 0x80000000, /**< Base FPA instruction set. */
+       ARM_FPU_FPA_EXT_V2     = 0x40000000, /**< LFM/SFM. */
+       ARM_FPU_VFP_EXT_NONE   = 0x20000000, /**< Use VFP word-ordering. */
+       ARM_FPU_VFP_EXT_V1xD   = 0x10000000, /**< Base VFP instruction set. */
+       ARM_FPU_VFP_EXT_V1     = 0x08000000, /**< Double-precision insns. */
+       ARM_FPU_VFP_EXT_V2     = 0x04000000, /**< ARM10E VFPr1. */
+
+       ARM_FPU_SOFTFLOAT      = 0x01000000, /**< soft float library */
+       ARM_FPU_NONE           = 0,
+
+       ARM_FPU_ARCH_FPE       = ARM_FPU_FPA_EXT_V1,
+       ARM_FPU_ARCH_FPA       = ARM_FPU_ARCH_FPE | ARM_FPU_FPA_EXT_V2,
+
+       ARM_FPU_ARCH_VFP       = ARM_FPU_VFP_EXT_NONE,
+       ARM_FPU_ARCH_VFP_V1xD  = ARM_FPU_VFP_EXT_V1xD | ARM_FPU_VFP_EXT_NONE,
+       ARM_FPU_ARCH_VFP_V1    = ARM_FPU_ARCH_VFP_V1xD | ARM_FPU_VFP_EXT_V1,
+       ARM_FPU_ARCH_VFP_V2    = ARM_FPU_ARCH_VFP_V1 | ARM_FPU_VFP_EXT_V2,
+
+       ARM_FPU_ARCH_SOFTFLOAT = ARM_FPU_SOFTFLOAT,
+
+       ARM_FPU_MASK           = 0xff000000,
+};
+
+/** Returns non-zero if FPA instructions should be issued. */
+#define USE_FPA(cg)     ((cg)->fpu_arch & ARM_FPU_FPA_EXT_V1)
+
+/** Returns non-zero if VFP instructions should be issued. */
+#define USE_VFP(cg)     ((cg)->fpu_arch & ARM_FPU_VFP_EXT_V1xD)
+
+/** Types of processor to generate code for. */
+enum arm_processor_types {
+       ARM_1      = ARM_ARCH_V1,
+       ARM_2      = ARM_ARCH_V2,
+       ARM_3      = ARM_ARCH_V2S,
+       ARM_250    = ARM_ARCH_V2S,
+       ARM_6      = ARM_ARCH_V3,
+       ARM_7      = ARM_ARCH_V3,
+       ARM_8      = ARM_ARCH_V4,
+       ARM_9      = ARM_ARCH_V4T,
+       ARM_STRONG = ARM_ARCH_V4,
+};
+
 typedef struct _arm_code_gen_t {
        const arch_code_generator_if_t *impl;           /**< implementation */
        ir_graph                       *irg;            /**< current irg */
@@ -34,6 +131,8 @@ struct _arm_isa_t {
        int                    gen_reg_names; /**< use generic register names instead of SP, LR, PC */
        arm_code_gen_t        *cg;            /**< current code generator */
        FILE                  *out;           /**< output file */
+
+       unsigned               fpu_arch;      /**< FPU architecture */
 };