#include "config.h"
#include <limits.h>
+#include <stdbool.h>
#include "xmalloc.h"
#include "tv.h"
return reg;
}
-/**
- * Emit the name of the source register at given input position.
- */
void arm_emit_source_register(const ir_node *node, int pos)
{
const arch_register_t *reg = get_in_reg(node, pos);
be_emit_string(arch_register_get_name(reg));
}
-/**
- * Emit the name of the destination register at given output position.
- */
void arm_emit_dest_register(const ir_node *node, int pos)
{
const arch_register_t *reg = get_out_reg(node, pos);
be_emit_string(arch_register_get_name(reg));
}
-/**
- * Emit a node's offset.
- */
void arm_emit_offset(const ir_node *node)
{
const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
be_emit_char(c);
}
-/**
- * Emit the instruction suffix depending on the mode.
- */
-void arm_emit_mode(const ir_node *node)
+void arm_emit_float_load_store_mode(const ir_node *node)
{
- ir_mode *mode;
+ const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
+ arm_emit_fpa_postfix(attr->load_store_mode);
+}
- if (is_arm_irn(node)) {
- const arm_attr_t *attr = get_arm_attr_const(node);
- mode = attr->op_mode ? attr->op_mode : get_irn_mode(node);
- } else {
- mode = get_irn_mode(node);
- }
- arm_emit_fpa_postfix(mode);
+void arm_emit_float_arithmetic_mode(const ir_node *node)
+{
+ const arm_farith_attr_t *attr = get_arm_farith_attr_const(node);
+ arm_emit_fpa_postfix(attr->mode);
+}
+
+void arm_emit_symconst(const ir_node *node)
+{
+ const arm_SymConst_attr_t *symconst = get_arm_SymConst_attr_const(node);
+ ir_entity *entity = symconst->entity;
+
+ be_gas_emit_entity(entity);
+
+ /* TODO do something with offset */
}
void arm_emit_load_mode(const ir_node *node)
}
}
-
-static void emit_shf_mod_name(arm_shift_modifier mod)
+static void emit_shf_mod_name(arm_shift_modifier_t mod)
{
switch (mod) {
case ARM_SHF_ASR_REG:
/** An entry in the sym_or_tv set. */
typedef struct sym_or_tv_t {
union {
- ident *id; /**< An ident. */
- tarval *tv; /**< A tarval. */
+ ir_entity *entity; /**< An entity. */
+ tarval *tv; /**< A tarval. */
const void *generic; /**< For generic compare. */
} u;
unsigned label; /**< the associated label. */
- char is_ident; /**< Non-zero if an ident is stored. */
+ bool is_entity; /**< true if an entity is stored. */
} sym_or_tv_t;
/**
return ++id;
}
+static void emit_constant_name(const sym_or_tv_t *entry)
+{
+ be_emit_irprintf("%sC%u", be_gas_get_private_prefix(), entry->label);
+}
+
/**
* Emit a SymConst.
*/
sym_or_tv_t key, *entry;
unsigned label;
- key.u.id = get_entity_ld_ident(attr->entity);
- key.is_ident = 1;
- key.label = 0;
+ key.u.entity = attr->entity;
+ key.is_entity = true;
+ key.label = 0;
entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
if (entry->label == 0) {
/* allocate a label */
/* load the symbol indirect */
be_emit_cstring("\tldr ");
arm_emit_dest_register(irn, 0);
- be_emit_irprintf(", .L%u", label);
+ be_emit_cstring(", ");
+ emit_constant_name(entry);
be_emit_finish_line_gas(irn);
}
/**
* Emit a floating point fpa constant.
*/
-static void emit_arm_fpaConst(const ir_node *irn)
+static void emit_arm_fConst(const ir_node *irn)
{
sym_or_tv_t key, *entry;
unsigned label;
ir_mode *mode;
- key.u.tv = get_fpaConst_value(irn);
- key.is_ident = 0;
- key.label = 0;
+ key.u.tv = get_fConst_value(irn);
+ key.is_entity = false;
+ key.label = 0;
entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
if (entry->label == 0) {
/* allocate a label */
be_emit_char(' ');
arm_emit_dest_register(irn, 0);
- be_emit_irprintf(", .L%u", label);
+ be_emit_cstring(", ");
+ emit_constant_name(entry);
be_emit_finish_line_gas(irn);
}
const ir_node *next_block;
ir_node *op1 = get_irn_n(irn, 0);
const char *suffix;
- int proj_num = get_arm_CondJmp_proj_num(irn);
+ pn_Cmp pnc = get_arm_CondJmp_pnc(irn);
const arm_cmp_attr_t *cmp_attr = get_irn_generic_attr_const(op1);
bool is_signed = !cmp_attr->is_unsigned;
}
if (cmp_attr->ins_permuted) {
- proj_num = get_mirrored_pnc(proj_num);
+ pnc = get_mirrored_pnc(pnc);
}
/* for now, the code works for scheduled and non-schedules blocks */
/* we have a block schedule */
next_block = sched_next_block(block);
- assert(proj_num != pn_Cmp_False);
- assert(proj_num != pn_Cmp_True);
+ assert(pnc != pn_Cmp_False);
+ assert(pnc != pn_Cmp_True);
if (get_cfop_target_block(proj_true) == next_block) {
/* exchange both proj's so the second one can be omitted */
proj_true = proj_false;
proj_false = t;
- proj_num = get_negated_pnc(proj_num, mode_Iu);
+ pnc = get_negated_pnc(pnc, mode_Iu);
}
- switch (proj_num) {
+ switch (pnc) {
case pn_Cmp_Eq: suffix = "eq"; break;
case pn_Cmp_Lt: suffix = is_signed ? "lt" : "lo"; break;
case pn_Cmp_Le: suffix = is_signed ? "le" : "ls"; break;
xfree(projs);
}
-/************************************************************************/
-/* emit_be */
-/************************************************************************/
-
-static void arm_emit_entity(ir_entity *entity)
-{
- be_emit_ident(get_entity_ld_ident(entity));
-}
-
-static void emit_be_Call(const ir_node *irn)
-{
- ir_entity *entity = be_Call_get_entity(irn);
-
- if (entity != NULL) {
- be_emit_cstring("\tbl ");
- arm_emit_entity(entity);
- be_emit_finish_line_gas(irn);
- } else {
- be_emit_cstring("\tmov lr, pc");
- be_emit_finish_line_gas(irn);
- be_emit_cstring("\tmov pc, ");
- arm_emit_source_register(irn, be_pos_Call_ptr);
- be_emit_finish_line_gas(irn);
- }
-}
-
/** Emit an IncSP node */
static void emit_be_IncSP(const ir_node *irn)
{
if (mode_is_float(mode)) {
if (USE_FPA(cg->isa)) {
be_emit_cstring("\tmvf");
- arm_emit_mode(irn);
be_emit_char(' ');
arm_emit_dest_register(irn, 0);
be_emit_cstring(", ");
be_emit_finish_line_gas(node);
}
-/************************************************************************/
-/* emit */
-/************************************************************************/
static void emit_arm_Jmp(const ir_node *node)
{
be_emit_finish_line_gas(node);
}
-static void emit_arm_fpaDbl2GP(const ir_node *irn)
-{
- be_emit_cstring("\tstfd ");
- arm_emit_source_register(irn, 0);
- be_emit_cstring(", [sp, #-8]!");
- be_emit_pad_comment();
- be_emit_cstring("/* Push fp to stack */");
- be_emit_finish_line_gas(NULL);
-
- be_emit_cstring("\tldmfd sp!, {");
- arm_emit_dest_register(irn, 1);
- be_emit_cstring(", ");
- arm_emit_dest_register(irn, 0);
- be_emit_char('}');
- be_emit_pad_comment();
- be_emit_cstring("/* Pop destination */");
- be_emit_finish_line_gas(irn);
-}
-
-static void emit_arm_LdTls(const ir_node *irn)
-{
- (void) irn;
- panic("TLS not supported for this target");
- /* Er... our gcc does not support it... Install a newer toolchain. */
-}
-
static void emit_nothing(const ir_node *irn)
{
(void) irn;
arm_register_spec_emitters();
/* custom emitter */
- set_emitter(op_arm_B, emit_arm_B);
- set_emitter(op_arm_CopyB, emit_arm_CopyB);
- set_emitter(op_arm_fpaConst, emit_arm_fpaConst);
- set_emitter(op_arm_fpaDbl2GP, emit_arm_fpaDbl2GP);
- set_emitter(op_arm_FrameAddr, emit_arm_FrameAddr);
- set_emitter(op_arm_Jmp, emit_arm_Jmp);
- set_emitter(op_arm_LdTls, emit_arm_LdTls);
- set_emitter(op_arm_SwitchJmp, emit_arm_SwitchJmp);
- set_emitter(op_arm_SymConst, emit_arm_SymConst);
- set_emitter(op_be_Call, emit_be_Call);
- set_emitter(op_be_Copy, emit_be_Copy);
- set_emitter(op_be_CopyKeep, emit_be_Copy);
- set_emitter(op_be_IncSP, emit_be_IncSP);
- set_emitter(op_be_MemPerm, emit_be_MemPerm);
- set_emitter(op_be_Perm, emit_be_Perm);
- set_emitter(op_be_Return, emit_be_Return);
+ set_emitter(op_arm_B, emit_arm_B);
+ set_emitter(op_arm_CopyB, emit_arm_CopyB);
+ set_emitter(op_arm_fConst, emit_arm_fConst);
+ set_emitter(op_arm_FrameAddr, emit_arm_FrameAddr);
+ set_emitter(op_arm_Jmp, emit_arm_Jmp);
+ set_emitter(op_arm_SwitchJmp, emit_arm_SwitchJmp);
+ set_emitter(op_arm_SymConst, emit_arm_SymConst);
+ set_emitter(op_be_Copy, emit_be_Copy);
+ set_emitter(op_be_CopyKeep, emit_be_Copy);
+ set_emitter(op_be_IncSP, emit_be_IncSP);
+ set_emitter(op_be_MemPerm, emit_be_MemPerm);
+ set_emitter(op_be_Perm, emit_be_Perm);
+ set_emitter(op_be_Return, emit_be_Return);
/* no need to emit anything for the following nodes */
- set_emitter(op_Phi, emit_nothing);
- set_emitter(op_be_Keep, emit_nothing);
- set_emitter(op_be_Start, emit_nothing);
- set_emitter(op_be_Barrier, emit_nothing);
+ set_emitter(op_Phi, emit_nothing);
+ set_emitter(op_be_Keep, emit_nothing);
+ set_emitter(op_be_Start, emit_nothing);
+ set_emitter(op_be_Barrier, emit_nothing);
}
/**
int n_cfgpreds;
int need_label;
int i, arity;
- ir_exec_freq *exec_freq = cg->birg->exec_freq;
+ ir_exec_freq *exec_freq = be_get_irg_exec_freq(cg->irg);
need_label = 0;
n_cfgpreds = get_Block_n_cfgpreds(block);
return p1->u.generic != p2->u.generic;
}
-/**
- * Main driver. Emits the code for one routine.
- */
void arm_gen_routine(const arm_code_gen_t *arm_cg, ir_graph *irg)
{
ir_node **blk_sched;
arm_register_emitters();
- be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi));
+ be_dbg_method_begin(entity);
- /* create the block schedule. For now, we don't need it earlier. */
- blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq);
+ /* create the block schedule */
+ blk_sched = be_create_block_schedule(irg);
be_gas_emit_function_prolog(entity, 4);
last_block = block;
}
- be_gas_emit_function_epilog(entity);
- be_dbg_method_end();
-
/* emit SymConst values */
if (set_count(sym_or_tv) > 0) {
sym_or_tv_t *entry;
be_emit_cstring("\t.align 2\n");
foreach_set(sym_or_tv, entry) {
- be_emit_irprintf(".L%u:\n", entry->label);
+ emit_constant_name(entry);
+ be_emit_cstring(":\n");
+ be_emit_write_line();
- if (entry->is_ident) {
+ if (entry->is_entity) {
be_emit_cstring("\t.word\t");
- be_emit_ident(entry->u.id);
+ be_gas_emit_entity(entry->u.entity);
be_emit_char('\n');
be_emit_write_line();
} else {
be_emit_write_line();
}
del_set(sym_or_tv);
+
+ be_gas_emit_function_epilog(entity);
+ be_dbg_method_end();
}
void arm_init_emitter(void)