X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Farm%2Farm_emitter.c;h=de458a0f3832c945d6e6f67881167f4db0c3ecb1;hb=18011a85e62d81f6d8d08957192fa34d03b747c5;hp=5f26f3f960a9ec3dbf91351da07d312c576e8132;hpb=c79fe4adc914d8d867772053bedf449a4f85645d;p=libfirm diff --git a/ir/be/arm/arm_emitter.c b/ir/be/arm/arm_emitter.c index 5f26f3f96..de458a0f3 100644 --- a/ir/be/arm/arm_emitter.c +++ b/ir/be/arm/arm_emitter.c @@ -26,6 +26,7 @@ #include "config.h" #include +#include #include "xmalloc.h" #include "tv.h" @@ -133,27 +134,18 @@ static const arch_register_t *get_out_reg(const ir_node *node, int pos) 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); @@ -177,20 +169,26 @@ static void arm_emit_fpa_postfix(const ir_mode *mode) 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) @@ -222,8 +220,7 @@ void arm_emit_store_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: @@ -298,12 +295,12 @@ void arm_emit_shifter_operand(const ir_node *node) /** 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; /** @@ -315,6 +312,11 @@ static unsigned get_unique_label(void) 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. */ @@ -324,9 +326,9 @@ static void emit_arm_SymConst(const ir_node *irn) 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 */ @@ -337,7 +339,8 @@ static void emit_arm_SymConst(const ir_node *irn) /* 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); } @@ -357,15 +360,15 @@ static void emit_arm_FrameAddr(const ir_node *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 */ @@ -380,7 +383,8 @@ static void emit_arm_fpaConst(const ir_node *irn) 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); } @@ -422,7 +426,7 @@ static void emit_arm_B(const ir_node *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; @@ -439,7 +443,7 @@ static void emit_arm_B(const ir_node *irn) } 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 */ @@ -448,8 +452,8 @@ static void emit_arm_B(const ir_node *irn) /* 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 */ @@ -457,10 +461,10 @@ static void emit_arm_B(const ir_node *irn) 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; @@ -719,32 +723,6 @@ static void emit_arm_SwitchJmp(const ir_node *irn) 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) { @@ -780,7 +758,6 @@ static void emit_be_Copy(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(", "); @@ -876,9 +853,6 @@ static void emit_be_Return(const ir_node *node) be_emit_finish_line_gas(node); } -/************************************************************************/ -/* emit */ -/************************************************************************/ static void emit_arm_Jmp(const ir_node *node) { @@ -900,32 +874,6 @@ 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; @@ -957,28 +905,25 @@ static void arm_register_emitters(void) 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); } /** @@ -1006,7 +951,7 @@ static void arm_emit_block_header(ir_node *block, ir_node *prev) 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); @@ -1097,9 +1042,6 @@ static int cmp_sym_or_tv(const void *elt, const void *key, size_t size) 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; @@ -1114,10 +1056,10 @@ void arm_gen_routine(const arm_code_gen_t *arm_cg, ir_graph *irg) 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); @@ -1137,9 +1079,6 @@ void arm_gen_routine(const arm_code_gen_t *arm_cg, ir_graph *irg) 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; @@ -1147,11 +1086,13 @@ void arm_gen_routine(const arm_code_gen_t *arm_cg, ir_graph *irg) 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 { @@ -1175,6 +1116,9 @@ void arm_gen_routine(const arm_code_gen_t *arm_cg, ir_graph *irg) be_emit_write_line(); } del_set(sym_or_tv); + + be_gas_emit_function_epilog(entity); + be_dbg_method_end(); } void arm_init_emitter(void)