implement sparc floatingpoint constants
authorMatthias Braun <matze@braunis.de>
Thu, 22 Jul 2010 19:08:04 +0000 (19:08 +0000)
committerMatthias Braun <matze@braunis.de>
Thu, 22 Jul 2010 19:08:04 +0000 (19:08 +0000)
[r27787]

ir/be/sparc/bearch_sparc.c
ir/be/sparc/bearch_sparc_t.h
ir/be/sparc/sparc_spec.pl
ir/be/sparc/sparc_transform.c

index 5dcba94..c9a6c1a 100644 (file)
@@ -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);
+               }
        }
 }
 
index a3fd752..5438903 100644 (file)
@@ -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 {
index fb97f01..1442e8c 100644 (file)
@@ -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
index 1f9cf47..de66fc3 100644 (file)
@@ -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);
 }
 
 /**