* @file
* @brief arm emitter
* @author Oliver Richter, Tobias Gneist, Michael Beck
- * @version $Id$
*/
#include "config.h"
#include "beblocksched.h"
#include "beirg.h"
#include "begnuas.h"
-#include "be_dbgout.h"
+#include "bedwarf.h"
#include "arm_emitter.h"
#include "arm_optimize.h"
#include "benode.h"
-#define SNPRINTF_BUF_LEN 128
-
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
static set *sym_or_tv;
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));
+ entry = set_insert(sym_or_tv_t, sym_or_tv, &key, sizeof(key), hash_ptr(key.u.generic));
if (entry->label == 0) {
/* allocate a label */
entry->label = get_unique_label();
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));
+ entry = set_insert(sym_or_tv_t, sym_or_tv, &key, sizeof(key), hash_ptr(key.u.generic));
if (entry->label == 0) {
/* allocate a label */
entry->label = get_unique_label();
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);
+ if (be_options.verbose_asm) {
+ 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("\tb ");
arm_emit_cfop_target(proj_false);
t2 = arch_register_get_name(tmpregs[2]);
t3 = arch_register_get_name(tmpregs[3]);
- be_emit_cstring("/* MemCopy (");
- be_emit_string(src);
- be_emit_cstring(")->(");
- arm_emit_source_register(irn, 0);
- be_emit_irprintf(" [%u bytes], Uses ", size);
- be_emit_string(t0);
- be_emit_cstring(", ");
- be_emit_string(t1);
- be_emit_cstring(", ");
- be_emit_string(t2);
- be_emit_cstring(", and ");
- be_emit_string(t3);
- be_emit_cstring("*/");
- be_emit_finish_line_gas(NULL);
+ if (be_options.verbose_asm) {
+ be_emit_cstring("/* MemCopy (");
+ be_emit_string(src);
+ be_emit_cstring(")->(");
+ arm_emit_source_register(irn, 0);
+ be_emit_irprintf(" [%u bytes], Uses ", size);
+ be_emit_string(t0);
+ be_emit_cstring(", ");
+ be_emit_string(t1);
+ be_emit_cstring(", ");
+ be_emit_string(t2);
+ be_emit_cstring(", and ");
+ be_emit_string(t3);
+ be_emit_cstring("*/");
+ be_emit_finish_line_gas(NULL);
+ }
assert(size > 0 && "CopyB needs size > 0" );
static void emit_arm_SwitchJmp(const ir_node *irn)
{
- const ir_edge_t *edge;
- ir_node *proj;
- int i;
- ir_node **projs;
- int n_projs;
- int block_nr;
- ir_node *default_proj = NULL;
-
- block_nr = get_irn_node_nr(irn);
- n_projs = get_arm_SwitchJmp_n_projs(irn);
-
- projs = XMALLOCNZ(ir_node*, n_projs);
-
- foreach_out_edge(irn, edge) {
- proj = get_edge_src_irn(edge);
- assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
-
- if (get_Proj_proj(proj) == get_arm_SwitchJmp_default_proj_num(irn))
- default_proj = proj;
-
- projs[get_Proj_proj(proj)] = proj;
- }
- assert(default_proj != NULL && "SwitchJmp should have a Default Proj");
-
- /*
- CMP %1S, n_projs - 1
- BHI default
- */
-
- be_emit_cstring("\tcmp ");
+ const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(irn);
+ be_emit_cstring("\tldrls pc, [pc, ");
arm_emit_source_register(irn, 0);
- be_emit_irprintf(", #%u", n_projs - 1);
+ be_emit_cstring(", asl #2]");
be_emit_finish_line_gas(irn);
- be_emit_cstring("\tbhi ");
- arm_emit_cfop_target(default_proj);
- be_emit_finish_line_gas(default_proj);
-
- /*
- LDR %r12, .TABLE_X_START
- ADD %r12, %r12, [%1S, LSL #2]
- LDR %r15, %r12
- */
-
- be_emit_irprintf("\tldr %%r12, TABLE_%d_START", block_nr);
- be_emit_finish_line_gas(NULL);
-
- be_emit_irprintf("\tadd %%r12, %%r12, ");
- arm_emit_source_register(irn, 0);
- be_emit_cstring(", LSL #2");
- be_emit_finish_line_gas(NULL);
-
- be_emit_cstring("\tldr %r15, [%r12, #0]");
- be_emit_finish_line_gas(NULL);
-
- be_emit_irprintf("TABLE_%d_START:\n\t.word\tTABLE_%d", block_nr, block_nr);
- be_emit_finish_line_gas(NULL);
- be_emit_irprintf("\t.align 2");
- be_emit_finish_line_gas(NULL);
- be_emit_irprintf("TABLE_%d:", block_nr);
- be_emit_finish_line_gas(NULL);
-
- for (i = 0; i < n_projs; ++i) {
- proj = projs[i];
- if (proj == NULL) {
- proj = projs[get_arm_SwitchJmp_default_proj_num(irn)];
- }
- be_emit_cstring("\t.word\t");
- arm_emit_cfop_target(proj);
- be_emit_finish_line_gas(proj);
- }
- be_emit_irprintf("\t.align 2\n");
- be_emit_finish_line_gas(NULL);
- xfree(projs);
+ be_emit_jump_table(irn, attr->table, NULL, get_cfop_target_block);
}
/** Emit an IncSP node */
if (get_cfop_target_block(node) != next_block) {
be_emit_cstring("\tb ");
arm_emit_cfop_target(node);
+ be_emit_finish_line_gas(node);
} else {
- be_emit_cstring("\t/* fallthrough to ");
- arm_emit_cfop_target(node);
- be_emit_cstring(" */");
+ if (be_options.verbose_asm) {
+ be_emit_cstring("\t/* fallthrough to ");
+ arm_emit_cfop_target(node);
+ be_emit_cstring(" */");
+ be_emit_finish_line_gas(node);
+ }
}
- be_emit_finish_line_gas(node);
}
static void emit_nothing(const ir_node *irn)
static void arm_register_emitters(void)
{
/* first clear the generic function pointer for all ops */
- clear_irp_opcodes_generic_func();
+ ir_clear_opcodes_generic_func();
/* register all emitter functions defined in spec */
arm_register_spec_emitters();
if (op->ops.generic) {
emit_func *emit = (emit_func *)op->ops.generic;
- be_dbg_set_dbg_info(get_irn_dbg_info(irn));
+ be_dwarf_location(get_irn_dbg_info(irn));
(*emit)(irn);
} else {
panic("Error: No emit handler for node %+F (graph %+F)\n",
- irn, current_ir_graph);
+ irn, get_irn_irg(irn));
}
}
*/
static void arm_emit_block_header(ir_node *block, ir_node *prev)
{
- int n_cfgpreds;
- int need_label;
- int i, arity;
- ir_graph *irg = get_irn_irg(block);
- ir_exec_freq *exec_freq = be_get_irg_exec_freq(irg);
+ bool need_label = false;
+ int n_cfgpreds;
- need_label = 0;
n_cfgpreds = get_Block_n_cfgpreds(block);
if (n_cfgpreds == 1) {
ir_node *pred = get_Block_cfgpred(block, 0);
* are no fallthroughs */
if (pred_block == prev &&
!(is_Proj(pred) && is_arm_SwitchJmp(get_Proj_pred(pred)))) {
- need_label = 0;
+ need_label = false;
} else {
- need_label = 1;
+ need_label = true;
}
} else {
- need_label = 1;
+ need_label = true;
}
- if (need_label) {
- be_gas_emit_block_name(block);
- be_emit_char(':');
-
- be_emit_pad_comment();
- be_emit_cstring(" /* preds:");
-
- /* emit list of pred blocks in comment */
- arity = get_irn_arity(block);
- for (i = 0; i < arity; ++i) {
- ir_node *predblock = get_Block_cfgpred_block(block, i);
- be_emit_irprintf(" %d", get_irn_node_nr(predblock));
- }
- } else {
- be_emit_cstring("\t/* ");
- be_gas_emit_block_name(block);
- be_emit_cstring(": ");
- }
- if (exec_freq != NULL) {
- be_emit_irprintf(" freq: %f",
- get_block_execfreq(exec_freq, block));
- }
- be_emit_cstring(" */\n");
- be_emit_write_line();
+ be_gas_begin_block(block, need_label);
}
/**
ir_node *irn;
arm_emit_block_header(block, prev_block);
- be_dbg_set_dbg_info(get_irn_dbg_info(block));
+ be_dwarf_location(get_irn_dbg_info(block));
sched_foreach(block, irn) {
arm_emit_node(irn);
}
/* create the block schedule */
blk_sched = be_create_block_schedule(irg);
- be_gas_emit_function_prolog(entity, 4);
+ be_gas_emit_function_prolog(entity, 4, NULL);
irg_block_walk_graph(irg, arm_gen_labels, NULL, NULL);
/* 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, sym_or_tv_t*, entry) {
+ foreach_set(sym_or_tv, sym_or_tv_t, entry) {
emit_constant_name(entry);
be_emit_cstring(":\n");
be_emit_write_line();