bescripts: Copy all common node attributes into the constructor variants.
[libfirm] / ir / be / sparc / sparc_lower64.c
1 /*
2  * Copyright (C) 1995-2010 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief    Sparc 64bit lowering
23  * @author   Matthias Braun
24  */
25 #include "config.h"
26
27 #include "bearch_sparc_t.h"
28 #include "error.h"
29 #include "gen_sparc_new_nodes.h"
30 #include "lower_dw.h"
31 #include "ircons_t.h"
32 #include "util.h"
33
34 static void lower64_add(ir_node *node, ir_mode *mode)
35 {
36         dbg_info *dbgi       = get_irn_dbg_info(node);
37         ir_node  *block      = get_nodes_block(node);
38         ir_node  *left       = get_Add_left(node);
39         ir_node  *right      = get_Add_right(node);
40         ir_node  *left_low   = get_lowered_low(left);
41         ir_node  *left_high  = get_lowered_high(left);
42         ir_node  *right_low  = get_lowered_low(right);
43         ir_node  *right_high = get_lowered_high(right);
44         ir_node  *addcc      = new_bd_sparc_AddCC_t(dbgi, block, left_low,
45                                                     right_low);
46         ir_node  *res_low    = new_r_Proj(addcc, mode_Iu, pn_sparc_AddCC_t_res);
47         ir_node  *res_flags  = new_r_Proj(addcc, mode_ANY, pn_sparc_AddCC_t_flags);
48         ir_node  *addx       = new_bd_sparc_AddX_t(dbgi, block, left_high,
49                                                    right_high, res_flags, mode);
50         ir_set_dw_lowered(node, res_low, addx);
51 }
52
53 static void lower64_sub(ir_node *node, ir_mode *mode)
54 {
55         dbg_info *dbgi       = get_irn_dbg_info(node);
56         ir_node  *block      = get_nodes_block(node);
57         ir_node  *left       = get_Sub_left(node);
58         ir_node  *right      = get_Sub_right(node);
59         ir_node  *left_low   = get_lowered_low(left);
60         ir_node  *left_high  = get_lowered_high(left);
61         ir_node  *right_low  = get_lowered_low(right);
62         ir_node  *right_high = get_lowered_high(right);
63         ir_node  *subcc      = new_bd_sparc_SubCC_t(dbgi, block, left_low,
64                                                     right_low);
65         ir_node  *res_low    = new_r_Proj(subcc, mode_Iu, pn_sparc_SubCC_t_res);
66         ir_node  *res_flags  = new_r_Proj(subcc, mode_ANY, pn_sparc_SubCC_t_flags);
67         ir_node  *subx       = new_bd_sparc_SubX_t(dbgi, block, left_high,
68                                                    right_high, res_flags, mode);
69         ir_set_dw_lowered(node, res_low, subx);
70 }
71
72 static void lower64_minus(ir_node *node, ir_mode *mode)
73 {
74         dbg_info *dbgi         = get_irn_dbg_info(node);
75         ir_graph *irg          = get_irn_irg(node);
76         ir_node  *block        = get_nodes_block(node);
77         ir_node  *op           = get_Minus_op(node);
78         ir_node  *right_low    = get_lowered_low(op);
79         ir_node  *right_high   = get_lowered_high(op);
80         ir_mode  *low_unsigned = get_irn_mode(right_low);
81         ir_node  *left_low     = new_r_Const(irg, get_mode_null(low_unsigned));
82         ir_node  *left_high    = new_r_Const(irg, get_mode_null(mode));
83         ir_node  *subcc        = new_bd_sparc_SubCC_t(dbgi, block, left_low,
84                                                       right_low);
85         ir_node  *res_low      = new_r_Proj(subcc, mode_Iu, pn_sparc_SubCC_t_res);
86         ir_node  *res_flags    = new_r_Proj(subcc, mode_ANY, pn_sparc_SubCC_t_flags);
87         ir_node  *subx         = new_bd_sparc_SubX_t(dbgi, block, left_high,
88                                                      right_high, res_flags, mode);
89         ir_set_dw_lowered(node, res_low, subx);
90 }
91
92 static ir_entity *create_64_intrinsic_fkt(ir_type *method, const ir_op *op,
93                                           const ir_mode *imode,
94                                           const ir_mode *omode, void *context)
95 {
96         ir_type    *glob = get_glob_type();
97         const char *name;
98         ident      *id;
99         ir_entity  *result;
100         (void) context;
101         (void) omode;
102
103         if (op == op_Mul) {
104                 name = "__muldi3";
105         } else if (op == op_Div) {
106                 name = mode_is_signed(imode) ? "__divdi3" : "__udivdi3";
107         } else if (op == op_Mod) {
108                 name = mode_is_signed(imode) ? "__moddi3" : "__umoddi3";
109         } else if (op == op_Conv) {
110                 if (mode_is_float(imode)) {
111                         assert(get_mode_size_bits(omode) == 64);
112                         if (get_mode_size_bits(imode) == 64) {
113                                 name = mode_is_signed(omode) ? "__fixdfdi" : "__fixunsdfdi";
114                         } else if (get_mode_size_bits(imode) == 32) {
115                                 name = mode_is_signed(omode) ? "__fixsfdi" : "__fixunssfdi";
116                         } else {
117                                 assert(get_mode_size_bits(imode) == 128);
118                                 panic("can't conver long double to long long yet");
119                         }
120                 } else if (mode_is_float(omode)) {
121                         assert(get_mode_size_bits(imode) == 64);
122                         if (get_mode_size_bits(omode) == 64) {
123                                 name = mode_is_signed(imode) ? "__floatdidf" : "__floatundidf";
124                         } else if (get_mode_size_bits(omode) == 32) {
125                                 name = mode_is_signed(imode) ? "__floatdisf" : "__floatundisf";
126                         } else {
127                                 assert(get_mode_size_bits(omode) == 128);
128                                 panic("can't convert long long to long double yet");
129                         }
130                 } else {
131                         panic("can't lower 64bit Conv");
132                 }
133         } else {
134                 panic("Can't lower unexpected 64bit operation %s", get_op_name(op));
135         }
136         id     = new_id_from_str(name);
137         result = new_entity(glob, id, method);
138         set_entity_ld_ident(result, id);
139         set_entity_visibility(result, ir_visibility_external);
140         return result;
141 }
142
143 void sparc_lower_64bit(void)
144 {
145         lwrdw_param_t lower_dw_params = {
146                 0,  /* big endian */
147                 64, /* doubleword size */
148                 create_64_intrinsic_fkt,
149                 NULL
150         };
151
152         /* make sure opcodes are initialized */
153         sparc_create_opcodes(&sparc_irn_ops);
154
155         ir_prepare_dw_lowering(&lower_dw_params);
156         ir_register_dw_lower_function(op_Add,   lower64_add);
157         ir_register_dw_lower_function(op_Minus, lower64_minus);
158         ir_register_dw_lower_function(op_Sub,   lower64_sub);
159         ir_lower_dw_ops();
160 }