*/
#define SILENCER
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
#include <limits.h>
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
-static const arch_env_t *arch_env = NULL;
static const arm_code_gen_t *cg;
-static const arm_isa_t *isa;
static set *sym_or_tv;
/**
in register we need. */
op = get_irn_n(irn, pos);
- reg = arch_get_irn_register(arch_env, op);
+ reg = arch_get_irn_register(op);
assert(reg && "no in register found");
/* in case of a joker register: just return a valid register */
if (arch_register_type_is(reg, joker)) {
- const arch_register_req_t *req;
-
- /* ask for the requirements */
- req = arch_get_register_req(arch_env, irn, pos);
+ const arch_register_req_t *req = arch_get_register_req(irn, pos);
if (arch_register_req_is(req, limited)) {
/* in case of limited requirements: get the first allowed register */
/* Proj with the corresponding projnum for the register */
if (get_irn_mode(node) != mode_T) {
- reg = arch_get_irn_register(arch_env, node);
+ reg = arch_get_irn_register(node);
} else if (is_arm_irn(node)) {
reg = get_arm_out_reg(node, pos);
} else {
proj = get_edge_src_irn(edge);
assert(is_Proj(proj) && "non-Proj from mode_T node");
if (get_Proj_proj(proj) == pos) {
- reg = arch_get_irn_register(arch_env, proj);
+ reg = arch_get_irn_register(proj);
break;
}
}
mod = get_arm_shift_modifier(node);
if (ARM_HAS_SHIFT(mod)) {
- long v = get_arm_imm_value(node);
+ int v = get_arm_imm_value(node);
- be_emit_irprintf(", %s #%l", arm_shf_mod_name(mod), v);
+ be_emit_irprintf(", %s #%d", arm_shf_mod_name(mod), v);
}
}
}
}
+
+/**
+ * Emit a Tst with conditional branch.
+ */
+static void emit_arm_TstBra(const ir_node *irn)
+{
+ const ir_edge_t *edge;
+ const ir_node *proj_true = NULL;
+ const ir_node *proj_false = NULL;
+ const ir_node *block;
+ const ir_node *next_block;
+ const char *suffix;
+ int proj_num = get_arm_CondJmp_proj_num(irn);
+
+ foreach_out_edge(irn, edge) {
+ ir_node *proj = get_edge_src_irn(edge);
+ long nr = get_Proj_proj(proj);
+ if (nr == pn_Cond_true) {
+ proj_true = proj;
+ } else {
+ proj_false = proj;
+ }
+ }
+
+ /* for now, the code works for scheduled and non-schedules blocks */
+ block = get_nodes_block(irn);
+
+ /* we have a block schedule */
+ next_block = sched_next_block(block);
+
+ assert(proj_num != pn_Cmp_False);
+ assert(proj_num != pn_Cmp_True);
+
+ if (get_cfop_target_block(proj_true) == next_block) {
+ /* exchange both proj's so the second one can be omitted */
+ const ir_node *t = proj_true;
+
+ proj_true = proj_false;
+ proj_false = t;
+ proj_num = get_negated_pnc(proj_num, mode_Iu);
+ }
+ 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(!"Cmp unsupported"); suffix = "al";
+ }
+ be_emit_cstring("\ttst ");
+ arm_emit_source_register(irn, 0);
+ be_emit_cstring(", ");
+ arm_emit_source_register(irn, 1);
+ be_emit_finish_line_gas(irn);
+
+ /* emit the true proj */
+ be_emit_irprintf("\tb%s ", suffix);
+ arm_emit_cfop_target(proj_true);
+ be_emit_finish_line_gas(proj_true);
+
+ if (get_cfop_target_block(proj_false) == next_block) {
+ be_emit_cstring("\t/* fallthrough to ");
+ arm_emit_cfop_target(proj_false);
+ be_emit_cstring(" */");
+ be_emit_finish_line_gas(proj_false);
+ } else {
+ be_emit_cstring("b ");
+ arm_emit_cfop_target(proj_false);
+ be_emit_finish_line_gas(proj_false);
+ }
+}
+
/**
* Emit a Compare with conditional branch.
*/
block_nr = get_irn_node_nr(irn);
n_projs = get_arm_SwitchJmp_n_projs(irn);
- projs = xcalloc(n_projs , sizeof(ir_node*));
+ projs = XMALLOCNZ(ir_node*, n_projs);
foreach_out_edge(irn, edge) {
proj = get_edge_src_irn(edge);
arm_emit_dest_register(irn, 0);
be_emit_cstring(", ");
arm_emit_source_register(irn, 0);
- be_emit_irprintf(", #%x", offs);
+ be_emit_irprintf(", #0x%X", offs);
} else {
/* omitted IncSP(0) */
return;
}
if (mode_is_float(mode)) {
- if (USE_FPA(isa)) {
+ if (USE_FPA(cg->isa)) {
be_emit_cstring("\tmvf");
arm_emit_mode(irn);
be_emit_char(' ');
static void emit_arm_LdTls(const ir_node *irn) {
(void) irn;
- panic("TLS not supported for this target\n");
+ panic("TLS not supported for this target");
/* Er... our gcc does not support it... Install a newer toolchain. */
}
/**
* Set a node emitter. Make it a bit more type safe.
*/
-static INLINE void set_emitter(ir_op *op, emit_func arm_emit_node) {
+static inline void set_emitter(ir_op *op, emit_func arm_emit_node) {
op->ops.generic = (op_func)arm_emit_node;
}
/* other emitter functions */
ARM_EMIT(CmpBra);
+ ARM_EMIT(TstBra);
ARM_EMIT(fpaCmfBra);
ARM_EMIT(fpaCmfeBra);
ARM_EMIT(CopyB);
* 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;
- int i, n;
- ir_node *last_block = NULL;
+ ir_node **blk_sched;
+ int i, n;
+ ir_node *last_block = NULL;
+ ir_entity *entity = get_irg_entity(irg);
cg = arm_cg;
- isa = (const arm_isa_t *)cg->arch_env;
- arch_env = cg->arch_env;
sym_or_tv = new_set(cmp_sym_or_tv, 8);
arm_register_emitters();
+ be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi));
+
/* create the block schedule. For now, we don't need it earlier. */
blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq);
last_block = block;
}
+ be_dbg_method_end();
+
/* emit SymConst values */
if (set_count(sym_or_tv) > 0) {
sym_or_tv_t *entry;