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;
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);
+ }
}
}
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 {
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
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,
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.
*
*/
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);
*/
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);
}
/**