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));
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');
}
/**
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;
}
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);
}
/**
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 {
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);
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);
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);
}
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;
}
- 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);
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);
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 {
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 {
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 {
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 {
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) {
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);
}
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) {
+
+}
/***********************************************************************************
// ARM_EMIT(Const);
ARM_EMIT(SymConst);
ARM_EMIT(SwitchJmp);
+ ARM_EMIT(fpaDbl2GP);
/* benode emitter */
BE_EMIT(Call);
* Emits code for function end
*/
void arm_emit_end(FILE *F, ir_graph *irg) {
+ fprintf(F, "\t.ident \"firmcc\"\n");
}
/**
/**
-* 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;
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) */
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);
}
#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;
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;
/**
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
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;
$arch = "arm";
-# $comment_string = 'WIRHABENKEINEKOMMENTARE';
$comment_string = '/*';
# the number of additional opcodes you want to register
# "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"
# },
#
{ "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 },
{ "name" => "f5", "type" => 2 },
{ "name" => "f6", "type" => 2 },
{ "name" => "f7", "type" => 2 },
- { "mode" => "mode_D" }
+ { "mode" => "mode_E" }
]
); # %reg_classes
"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" => {
"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" => {
"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" => {
"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" => {
"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" => {
"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;'
},
"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" => {
"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" => {
"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" => {
"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
"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" => {
"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;'
},
"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" => {
"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" => {
"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" => {
"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;'
},
"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) */'
#},
"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" => {
"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;'
},
"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" => {
"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" => {
"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
"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);'
"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" ],
},
"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" ],
},
"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" ],
},
"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" ],
},
"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" ],
},
"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" ],
},
"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" ],
},
"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" ],
},
"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" ],
},
"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" ],
},
"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" ],
},
"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
-/* The codegenrator (transform FIRM into arm FIRM */
+/* The codegenerator (transform FIRM into arm FIRM */
/* $Id$ */
#ifdef HAVE_CONFIG_H
}
-
+/**
+ * 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) {
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
}
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;
}
/**
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))
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);
}
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) \
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))
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);
}
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));
}
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));
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));
*
*********************************************************/
-/************************************************************************/
-/* 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;
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),
#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"
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));
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)
{
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;
}
/**
- * 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;
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,
};
0, /* use generic register names instead of SP, LR, PC */
NULL, /* current code generator */
NULL, /* output file */
+ ARM_FPU_ARCH_FPE, /* FPU architecture */
};
/**
* 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];
}
/**
*/
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];
}
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);
}
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]);
}
}
}
#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 }
};
*
* 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)
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 */
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 */
};