X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fsparc%2Fbearch_sparc.c;h=5dcba946afe10335892e782090e8cce82717524b;hb=c563dd6506ad94733626b2c83fb7b017f90f37f7;hp=98dff711aa1791f24e76932b2334a0f720b89baf;hpb=ca21c59ea00ff05918de26952e91ac39f1589e01;p=libfirm diff --git a/ir/be/sparc/bearch_sparc.c b/ir/be/sparc/bearch_sparc.c index 98dff711a..5dcba946a 100644 --- a/ir/be/sparc/bearch_sparc.c +++ b/ir/be/sparc/bearch_sparc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2010 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -20,15 +20,13 @@ /** * @file * @brief The main sparc backend driver file. - * @version $Id: bearch_TEMPLATE.c 26673 2009-10-01 16:43:13Z matze $ + * @version $Id$ */ - #include "config.h" #include "lc_opts.h" #include "lc_opts_enum.h" -#include "pseudo_irg.h" #include "irgwalk.h" #include "irprog.h" #include "irprintf.h" @@ -36,13 +34,14 @@ #include "irgmod.h" #include "irgopt.h" #include "iroptimize.h" +#include "irtools.h" +#include "irdump.h" #include "lowering.h" -#include "error.h" #include "bitset.h" #include "debug.h" #include "array_t.h" -#include "irtools.h" +#include "error.h" #include "../bearch.h" #include "../benode.h" @@ -65,7 +64,6 @@ #include "gen_sparc_regalloc_if.h" #include "sparc_transform.h" #include "sparc_emitter.h" -#include "sparc_map_regs.h" DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) @@ -94,14 +92,6 @@ static ir_entity *sparc_get_frame_entity(const ir_node *irn) return NULL; } -static void sparc_set_frame_entity(ir_node *node, ir_entity *ent) -{ - (void) node; - (void) ent; - panic("sparc_set_frame_entity() called. This should not happen."); - /* TODO: set the ir_entity assigned to the frame */ -} - /** * This function is called by the generic backend to correct offsets for * nodes accessing the stack. @@ -118,9 +108,16 @@ static void sparc_set_frame_offset(ir_node *irn, int offset) } } -static int sparc_get_sp_bias(const ir_node *irn) +static int sparc_get_sp_bias(const ir_node *node) { - (void) irn; + if (is_sparc_Save(node)) { + const sparc_save_attr_t *attr = get_sparc_save_attr_const(node); + /* Note we do not retport the change of the SPARC_MIN_STACKSIZE + * size, since we have additional magic in the emitter which + * calculates that! */ + assert(attr->initial_stacksize >= SPARC_MIN_STACKSIZE); + return attr->initial_stacksize - SPARC_MIN_STACKSIZE; + } return 0; } @@ -130,7 +127,6 @@ static const arch_irn_ops_t sparc_irn_ops = { get_sparc_in_req, sparc_classify, sparc_get_frame_entity, - sparc_set_frame_entity, sparc_set_frame_offset, sparc_get_sp_bias, NULL, /* get_inverse */ @@ -153,23 +149,11 @@ static void sparc_prepare_graph(void *self) sparc_transform_graph(cg); if (cg->dump) - be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched); + dump_ir_graph(cg->irg, "transformed"); } -/** - * Called immediatly before emit phase. - */ -static void sparc_finish_irg(void *self) -{ - sparc_code_gen_t *cg = self; - ir_graph *irg = cg->irg; - - dump_ir_block_graph_sched(irg, "-sparc-finished"); -} - - static ir_node *sparc_flags_remat(ir_node *node, ir_node *after) { ir_node *block; @@ -190,7 +174,7 @@ static void sparc_before_ra(void *self) { sparc_code_gen_t *cg = self; /* fixup flags register */ - be_sched_fix_flags(cg->birg, &sparc_reg_classes[CLASS_sparc_flags], &sparc_flags_remat); + be_sched_fix_flags(cg->irg, &sparc_reg_classes[CLASS_sparc_flags], &sparc_flags_remat); } /** @@ -211,11 +195,11 @@ static void transform_Reload(ir_node *node) ir_node *sched_point = sched_prev(node); - load = new_bd_sparc_Load(dbgi, block, ptr, mem, mode, entity, false, 0, true); + load = new_bd_sparc_Ld(dbgi, block, ptr, mem, mode, entity, false, 0, true); sched_add_after(sched_point, load); sched_remove(node); - proj = new_rd_Proj(dbgi, load, mode, pn_sparc_Load_res); + proj = new_rd_Proj(dbgi, load, mode, pn_sparc_Ld_res); reg = arch_get_irn_register(node); arch_set_irn_register(proj, reg); @@ -240,7 +224,7 @@ static void transform_Spill(ir_node *node) ir_node *store; sched_point = sched_prev(node); - store = new_bd_sparc_Store(dbgi, block, ptr, val, mem, mode, entity, false, 0, true); + store = new_bd_sparc_St(dbgi, block, ptr, val, mem, mode, entity, false, 0, true); sched_remove(node); sched_add_after(sched_point, store); @@ -270,7 +254,7 @@ static void sparc_after_ra_walker(ir_node *block, void *data) static void sparc_after_ra(void *self) { sparc_code_gen_t *cg = self; - be_coalesce_spillslots(cg->birg); + be_coalesce_spillslots(cg->irg); irg_block_walk_graph(cg->irg, NULL, sparc_after_ra_walker, NULL); } @@ -292,70 +276,129 @@ static void sparc_emit_and_done(void *self) free(cg); } -static void *sparc_cg_init(be_irg_t *birg); +static void *sparc_cg_init(ir_graph *irg); static const arch_code_generator_if_t sparc_code_gen_if = { sparc_cg_init, - NULL, /* get_pic_base hook */ - NULL, /* before abi introduce hook */ + NULL, /* get_pic_base hook */ + NULL, /* before abi introduce hook */ sparc_prepare_graph, - NULL, /* spill hook */ + NULL, /* spill hook */ sparc_before_ra, /* before register allocation hook */ sparc_after_ra, /* after register allocation hook */ - sparc_finish_irg, + NULL, sparc_emit_and_done }; /** * Initializes the code generator. */ -static void *sparc_cg_init(be_irg_t *birg) +static void *sparc_cg_init(ir_graph *irg) { - static ir_type *int_tp = NULL; - sparc_isa_t *isa = (sparc_isa_t *)birg->main_env->arch_env; - sparc_code_gen_t *cg; - - if (! int_tp) { - /* create an integer type with machine size */ - int_tp = new_type_primitive(mode_Is); - } + sparc_isa_t *isa = (sparc_isa_t *) be_get_irg_arch_env(irg); + sparc_code_gen_t *cg = XMALLOCZ(sparc_code_gen_t); - cg = XMALLOC(sparc_code_gen_t); - cg->impl = &sparc_code_gen_if; - cg->irg = birg->irg; - //cg->reg_set = new_set(arm_cmp_irn_reg_assoc, 1024); - cg->isa = isa; - cg->birg = birg; - //cg->int_tp = int_tp; - //cg->have_fp_insn = 0; - //cg->unknown_gp = NULL; - //cg->unknown_fpa = NULL; - cg->dump = (birg->main_env->options->dump_flags & DUMP_BE) ? 1 : 0; + cg->impl = &sparc_code_gen_if; + cg->irg = irg; + cg->isa = isa; + cg->dump = (be_get_irg_options(irg)->dump_flags & DUMP_BE) != 0; /* enter the current code generator */ isa->cg = cg; - return (arch_code_generator_t *)cg; + return (arch_code_generator_t*) cg; } - - const arch_isa_if_t sparc_isa_if; static sparc_isa_t sparc_isa_template = { { - &sparc_isa_if, /* isa interface implementation */ + &sparc_isa_if, /* isa interface implementation */ &sparc_gp_regs[REG_SP], /* stack pointer register */ &sparc_gp_regs[REG_FP], /* base pointer register */ &sparc_reg_classes[CLASS_sparc_gp], /* link pointer register class */ -1, /* stack direction */ - 1, /* power of two stack alignment for calls, 2^2 == 4 */ + 3, /* power of two stack alignment for calls, 2^2 == 4 */ NULL, /* main environment */ 7, /* costs for a spill instruction */ 5, /* costs for a reload instruction */ + false, /* no custom abi handling */ }, NULL /* current code generator */ }; + +static void sparc_handle_intrinsics(void) +{ + ir_type *tp, *int_tp, *uint_tp; + i_record records[8]; + int n_records = 0; + + runtime_rt rt_iMod, rt_uMod; + +#define ID(x) new_id_from_chars(x, sizeof(x)-1) + + int_tp = new_type_primitive(mode_Is); + uint_tp = new_type_primitive(mode_Iu); + + + /* SPARC has no signed mod instruction ... */ + { + i_instr_record *map_Mod = &records[n_records++].i_instr; + + tp = new_type_method(2, 1); + set_method_param_type(tp, 0, int_tp); + set_method_param_type(tp, 1, int_tp); + set_method_res_type(tp, 0, int_tp); + + rt_iMod.ent = new_entity(get_glob_type(), ID(".rem"), tp); + set_entity_ld_ident(rt_iMod.ent, ID(".rem")); + rt_iMod.mode = mode_T; + rt_iMod.res_mode = mode_Is; + rt_iMod.mem_proj_nr = pn_Mod_M; + rt_iMod.regular_proj_nr = pn_Mod_X_regular; + rt_iMod.exc_proj_nr = pn_Mod_X_except; + rt_iMod.exc_mem_proj_nr = pn_Mod_M; + rt_iMod.res_proj_nr = pn_Mod_res; + + set_entity_visibility(rt_iMod.ent, ir_visibility_external); + + map_Mod->kind = INTRINSIC_INSTR; + map_Mod->op = op_Mod; + map_Mod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall; + map_Mod->ctx = &rt_iMod; + } + /* ... nor an unsigned mod. */ + { + i_instr_record *map_Mod = &records[n_records++].i_instr; + + tp = new_type_method(2, 1); + set_method_param_type(tp, 0, uint_tp); + set_method_param_type(tp, 1, uint_tp); + set_method_res_type(tp, 0, uint_tp); + + rt_uMod.ent = new_entity(get_glob_type(), ID(".urem"), tp); + set_entity_ld_ident(rt_uMod.ent, ID(".urem")); + rt_uMod.mode = mode_T; + rt_uMod.res_mode = mode_Iu; + rt_uMod.mem_proj_nr = pn_Mod_M; + rt_uMod.regular_proj_nr = pn_Mod_X_regular; + rt_uMod.exc_proj_nr = pn_Mod_X_except; + rt_uMod.exc_mem_proj_nr = pn_Mod_M; + rt_uMod.res_proj_nr = pn_Mod_res; + + set_entity_visibility(rt_uMod.ent, ir_visibility_external); + + map_Mod->kind = INTRINSIC_INSTR; + map_Mod->op = op_Mod; + map_Mod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall; + map_Mod->ctx = &rt_uMod; + } + + if (n_records > 0) + lower_intrinsics(records, n_records, /*part_block_used=*/0); +} + + /** * Initializes the backend ISA */ @@ -375,8 +418,9 @@ static arch_env_t *sparc_init(FILE *outfile) sparc_register_init(); sparc_create_opcodes(&sparc_irn_ops); + sparc_handle_intrinsics(); - return &isa->arch_env; + return &isa->base; } @@ -389,7 +433,7 @@ static void sparc_done(void *self) sparc_isa_t *isa = self; /* emit now all global declarations */ - be_gas_emit_decls(isa->arch_env.main_env); + be_gas_emit_decls(isa->base.main_env); be_emit_exit(); free(self); @@ -415,7 +459,7 @@ static const arch_register_class_t *sparc_get_reg_class(unsigned i) * @param mode The mode in question. * @return A register class which can hold values of the given mode. */ -const arch_register_class_t *sparc_get_reg_class_for_mode(const ir_mode *mode) +static const arch_register_class_t *sparc_get_reg_class_for_mode(const ir_mode *mode) { if (mode_is_float(mode)) return &sparc_reg_classes[CLASS_sparc_fp]; @@ -427,17 +471,15 @@ const arch_register_class_t *sparc_get_reg_class_for_mode(const ir_mode *mode) typedef struct { be_abi_call_flags_bits_t flags; - const arch_env_t *arch_env; - ir_graph *irg; + ir_graph *irg; } sparc_abi_env_t; -static void *sparc_abi_init(const be_abi_call_t *call, const arch_env_t *arch_env, ir_graph *irg) +static void *sparc_abi_init(const be_abi_call_t *call, ir_graph *irg) { sparc_abi_env_t *env = XMALLOC(sparc_abi_env_t); be_abi_call_flags_t fl = be_abi_call_get_flags(call); env->flags = fl.bits; env->irg = irg; - env->arch_env = arch_env; return env; } @@ -453,33 +495,52 @@ static ir_type *sparc_get_between_type(void *self) if (between_type == NULL) { between_type = new_type_class(new_id_from_str("sparc_between_type")); - set_type_size_bytes(between_type, 0); + set_type_size_bytes(between_type, SPARC_MIN_STACKSIZE); } return between_type; } + /** * Build the prolog, return the BASE POINTER register */ static const arch_register_t *sparc_abi_prologue(void *self, ir_node **mem, - pmap *reg_map, int *stack_bias) + pmap *reg_map, int *stack_bias) { sparc_abi_env_t *env = self; + ir_node *block = get_irg_start_block(env->irg); + const arch_register_t *fp = &sparc_gp_regs[REG_FP]; + const arch_register_t *sp = &sparc_gp_regs[REG_SP]; + + // sp + ir_node *sp_proj = be_abi_reg_map_get(reg_map, sp); + + + //ir_type *frame_type = get_irg_frame_type(env->irg); + //frame_alloc_area(frame_type, reserved_stack_size, 1, 1); + + // alloc min required stack space + // TODO: the min stacksize depends on wether this is a leaf procedure or not + ir_node *save = new_bd_sparc_Save(NULL, block, sp_proj, *mem, SPARC_MIN_STACKSIZE); + (void) reg_map; (void) mem; (void) stack_bias; - if (env->flags.try_omit_fp) - return env->arch_env->sp; + sp_proj = new_r_Proj(save, sp->reg_class->mode, pn_sparc_Save_stack); + *mem = new_r_Proj(save, mode_M, pn_sparc_Save_mem); + + arch_set_irn_register(sp_proj, sp); + be_abi_reg_map_set(reg_map, sp, sp_proj); - //panic("framepointer not implemented yet"); - return env->arch_env->bp; + // we always have a framepointer + return fp; } /* Build the epilog */ static void sparc_abi_epilogue(void *self, ir_node *bl, ir_node **mem, - pmap *reg_map) + pmap *reg_map) { (void) self; (void) bl; @@ -495,14 +556,50 @@ static const be_abi_callbacks_t sparc_abi_callbacks = { sparc_abi_epilogue, }; +static const arch_register_t *gp_param_out_regs[] = { + &sparc_gp_regs[REG_O0], + &sparc_gp_regs[REG_O1], + &sparc_gp_regs[REG_O2], + &sparc_gp_regs[REG_O3], + &sparc_gp_regs[REG_O4], + &sparc_gp_regs[REG_O5], +}; + +static const arch_register_t *gp_param_in_regs[] = { + &sparc_gp_regs[REG_I0], + &sparc_gp_regs[REG_I1], + &sparc_gp_regs[REG_I2], + &sparc_gp_regs[REG_I3], + &sparc_gp_regs[REG_I4], + &sparc_gp_regs[REG_I5], +}; + +/** + * get register for outgoing parameters 1-6 + */ +static const arch_register_t *sparc_get_RegParamOut_reg(int n) +{ + assert(n < 6 && n >=0 && "trying to get (out) register for param >= 6"); + return gp_param_out_regs[n]; +} + +/** + * get register for incoming parameters 1-6 + */ +static const arch_register_t *sparc_get_RegParamIn_reg(int n) +{ + assert(n < 6 && n >=0 && "trying to get (in) register for param >= 6"); + return gp_param_in_regs[n]; +} + /** * Get the ABI restrictions for procedure calls. * @param self The this pointer. * @param method_type The type of the method (procedure) in question. * @param abi The abi object to be modified */ -void sparc_get_call_abi(const void *self, ir_type *method_type, - be_abi_call_t *abi) +static void sparc_get_call_abi(const void *self, ir_type *method_type, + be_abi_call_t *abi) { ir_type *tp; ir_mode *mode; @@ -513,7 +610,7 @@ void sparc_get_call_abi(const void *self, ir_type *method_type, /* set abi flags for calls */ call_flags.bits.left_to_right = 0; call_flags.bits.store_args_sequential = 1; - call_flags.bits.try_omit_fp = 1; + call_flags.bits.try_omit_fp = 0; call_flags.bits.fp_free = 0; call_flags.bits.call_has_imm = 1; @@ -524,28 +621,32 @@ void sparc_get_call_abi(const void *self, ir_type *method_type, /* reg = get reg for param i; */ /* be_abi_call_param_reg(abi, i, reg); */ - /* pass args 0-5 via registers, remaining via stack */ + /* pass outgoing params 0-5 via registers, remaining via stack */ + /* on sparc we need to set the ABI context since register names of parameters change to i0-i5 if we are the callee */ if (i < 6) { - be_abi_call_param_reg(abi, i, sparc_get_RegParam_reg(i)); + be_abi_call_param_reg(abi, i, sparc_get_RegParamOut_reg(i), ABI_CONTEXT_CALLER); + be_abi_call_param_reg(abi, i, sparc_get_RegParamIn_reg(i), ABI_CONTEXT_CALLEE); } else { tp = get_method_param_type(method_type, i); mode = get_type_mode(tp); - be_abi_call_param_stack(abi, i, mode, 4, 0, 0); + be_abi_call_param_stack(abi, i, mode, 4, 0, 0, ABI_CONTEXT_BOTH); /*< stack args have no special context >*/ } } - /* TODO: set correct return register */ - /* default: return value is in O0 resp. F0 */ + /* set return value register: return value is in i0 resp. f0 */ if (get_method_n_ress(method_type) > 0) { tp = get_method_res_type(method_type, 0); mode = get_type_mode(tp); be_abi_call_res_reg(abi, 0, - mode_is_float(mode) ? &sparc_fp_regs[REG_F0] : &sparc_gp_regs[REG_O0]); + mode_is_float(mode) ? &sparc_fp_regs[REG_F0] : &sparc_gp_regs[REG_I0], ABI_CONTEXT_CALLEE); /*< return has no special context >*/ + + be_abi_call_res_reg(abi, 0, + mode_is_float(mode) ? &sparc_fp_regs[REG_F0] : &sparc_gp_regs[REG_O0], ABI_CONTEXT_CALLER); /*< return has no special context >*/ } } -int sparc_to_appear_in_schedule(void *block_env, const ir_node *irn) +static int sparc_to_appear_in_schedule(void *block_env, const ir_node *irn) { (void) block_env; @@ -623,20 +724,18 @@ static const be_execution_unit_t ***sparc_get_allowed_execution_units( { (void) irn; /* TODO */ - assert(0); - return NULL; + panic("sparc_get_allowed_execution_units not implemented yet"); } static const be_machine_t *sparc_get_machine(const void *self) { (void) self; /* TODO */ - assert(0); - return NULL; + panic("sparc_get_machine not implemented yet"); } static ir_graph **sparc_get_backend_irg_list(const void *self, - ir_graph ***irgs) + ir_graph ***irgs) { (void) self; (void) irgs; @@ -667,7 +766,7 @@ const arch_isa_if_t sparc_isa_if = { sparc_get_list_sched_selector, sparc_get_ilp_sched_selector, sparc_get_reg_class_alignment, - sparc_get_backend_params, + sparc_get_backend_params, sparc_get_allowed_execution_units, sparc_get_machine, sparc_get_backend_irg_list, @@ -676,6 +775,7 @@ const arch_isa_if_t sparc_isa_if = { sparc_is_valid_clobber }; +BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_sparc); void be_init_arch_sparc(void) { be_register_isa_if("sparc", &sparc_isa_if); @@ -683,4 +783,3 @@ void be_init_arch_sparc(void) sparc_init_transform(); sparc_init_emitter(); } -BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_sparc);