From: Matthias Braun Date: Thu, 22 Jul 2010 19:08:04 +0000 (+0000) Subject: implement sparc floatingpoint constants X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=4ec0521f2be686bded8267a9613e9612d06c4cd3;p=libfirm implement sparc floatingpoint constants [r27787] --- diff --git a/ir/be/sparc/bearch_sparc.c b/ir/be/sparc/bearch_sparc.c index 5dcba946a..c9a6c1a09 100644 --- a/ir/be/sparc/bearch_sparc.c +++ b/ir/be/sparc/bearch_sparc.c @@ -298,10 +298,11 @@ static void *sparc_cg_init(ir_graph *irg) sparc_isa_t *isa = (sparc_isa_t *) be_get_irg_arch_env(irg); sparc_code_gen_t *cg = XMALLOCZ(sparc_code_gen_t); - cg->impl = &sparc_code_gen_if; - cg->irg = irg; - cg->isa = isa; - cg->dump = (be_get_irg_options(irg)->dump_flags & DUMP_BE) != 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; + cg->constants = pmap_create(); /* enter the current code generator */ isa->cg = cg; @@ -618,31 +619,42 @@ static void sparc_get_call_abi(const void *self, ir_type *method_type, be_abi_call_set_flags(abi, call_flags, &sparc_abi_callbacks); for (i = 0; i < n; i++) { - /* reg = get reg for param i; */ - /* be_abi_call_param_reg(abi, i, reg); */ - - /* 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_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, ABI_CONTEXT_BOTH); /*< stack args have no special context >*/ + ir_type *type = get_method_param_type(method_type, i); + ir_mode *mode = get_type_mode(type); + + if (mode_is_float(mode) || i >= 6) { + unsigned align = get_type_size_bytes(type); + be_abi_call_param_stack(abi, i, mode, align, 0, 0, + ABI_CONTEXT_BOTH); + continue; } + + /* pass integer params 0-5 via registers. + * On sparc we need to set the ABI context since register names of + * parameters change to i0-i5 if we are the callee */ + 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); } - /* 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); + n = get_method_n_ress(method_type); + /* more than 1 result not supported */ + assert(n <= 1); + for (i = 0; i < n; ++i) { + tp = get_method_res_type(method_type, i); 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_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 >*/ + /* set return value register: return value is in i0 resp. f0 */ + if (mode_is_float(mode)) { + be_abi_call_res_reg(abi, i, &sparc_fp_regs[REG_F0], + ABI_CONTEXT_BOTH); + } else { + be_abi_call_res_reg(abi, i, &sparc_gp_regs[REG_I0], + ABI_CONTEXT_CALLEE); + be_abi_call_res_reg(abi, i, &sparc_gp_regs[REG_O0], + ABI_CONTEXT_CALLER); + } } } diff --git a/ir/be/sparc/bearch_sparc_t.h b/ir/be/sparc/bearch_sparc_t.h index a3fd7528f..543890309 100644 --- a/ir/be/sparc/bearch_sparc_t.h +++ b/ir/be/sparc/bearch_sparc_t.h @@ -38,6 +38,7 @@ typedef struct sparc_code_gen_t { sparc_isa_t *isa; /**< the isa instance */ bool dump; /**< set to 1 if graphs should be dumped */ + pmap *constants; } sparc_code_gen_t; struct sparc_isa_t { diff --git a/ir/be/sparc/sparc_spec.pl b/ir/be/sparc/sparc_spec.pl index fb97f0158..1442e8ccd 100644 --- a/ir/be/sparc/sparc_spec.pl +++ b/ir/be/sparc/sparc_spec.pl @@ -503,4 +503,15 @@ FdTOi => { emit =>'. FdTOi %S1, %D1' }, +Ldf => { + op_flags => [ "labeled", "fragile" ], + state => "exc_pinned", + ins => [ "ptr", "mem" ], + outs => [ "res", "M" ], + reg_req => { in => [ "gp", "none" ], out => [ "fp", "none" ] }, + attr_type => "sparc_load_store_attr_t", + attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity", + emit => '. ld [%S1%O], %D1' +}, + ); # end of %nodes diff --git a/ir/be/sparc/sparc_transform.c b/ir/be/sparc/sparc_transform.c index 1f9cf472b..de66fc358 100644 --- a/ir/be/sparc/sparc_transform.c +++ b/ir/be/sparc/sparc_transform.c @@ -173,17 +173,6 @@ static ir_node *create_const_graph(ir_node *irn, ir_node *block) return create_const_graph_value(dbgi, block, value); } -/** - * create a DAG to load fp constant. sparc only supports loading from global memory - */ -static ir_node *create_fp_const_graph(ir_node *irn, ir_node *block) -{ - (void) block; - (void) irn; - panic("FP constants not implemented"); -} - - typedef enum { MATCH_NONE = 0, MATCH_COMMUTATIVE = 1 << 0, @@ -557,6 +546,42 @@ static ir_node *gen_Minus(ir_node *node) return new_bd_sparc_Minus(dbgi, block, new_op); } +static ir_node *make_addr(dbg_info *dbgi, ir_entity *entity) +{ + ir_node *block = get_irg_start_block(current_ir_graph); + ir_node *node = new_bd_sparc_SymConst(dbgi, block, entity); + be_dep_on_frame(node); + return node; +} + +/** + * Create an entity for a given (floatingpoint) tarval + */ +static ir_entity *create_float_const_entity(tarval *tv) +{ + ir_entity *entity = (ir_entity*) pmap_get(env_cg->constants, tv); + ir_initializer_t *initializer; + ir_mode *mode; + ir_type *type; + ir_type *glob; + + if (entity != NULL) + return entity; + + mode = get_tarval_mode(tv); + type = get_type_for_mode(mode); + glob = get_glob_type(); + entity = new_entity(glob, id_unique("C%u"), type); + set_entity_visibility(entity, ir_visibility_private); + add_entity_linkage(entity, IR_LINKAGE_CONSTANT); + + initializer = create_initializer_tarval(tv); + set_entity_initializer(entity, initializer); + + pmap_insert(env_cg->constants, tv, entity); + return entity; +} + /** * Transforms a Const node. * @@ -565,14 +590,20 @@ static ir_node *gen_Minus(ir_node *node) */ static ir_node *gen_Const(ir_node *node) { - ir_node *block = be_transform_node(get_nodes_block(node)); - ir_mode *mode = get_irn_mode(node); - dbg_info *dbg = get_irn_dbg_info(node); - - (void) dbg; + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_mode *mode = get_irn_mode(node); if (mode_is_float(mode)) { - return create_fp_const_graph(node, block); + dbg_info *dbgi = get_irn_dbg_info(node); + tarval *tv = get_Const_tarval(node); + ir_entity *entity = create_float_const_entity(tv); + ir_node *addr = make_addr(dbgi, entity); + ir_node *mem = new_NoMem(); + ir_node *new_op + = new_bd_sparc_Ldf(dbgi, block, addr, mem, mode, NULL, 0, 0, false); + + ir_node *proj = new_Proj(new_op, mode, pn_sparc_Ldf_res); + return proj; } return create_const_graph(node, block); @@ -806,14 +837,10 @@ static ir_node *gen_Cmp(ir_node *node) */ static ir_node *gen_SymConst(ir_node *node) { - ir_node *block = be_transform_node(get_nodes_block(node)); ir_entity *entity = get_SymConst_entity(node); dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *new_node; - new_node = new_bd_sparc_SymConst(dbgi, block, entity); - be_dep_on_frame(new_node); - return new_node; + return make_addr(dbgi, entity); } /**