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 "gen_sparc_new_nodes.h"
29 #include "lower_dw.h"
30 #include "ircons_t.h"
31 #include "util.h"
32
lower64_add(ir_node * node,ir_mode * mode)33 static void lower64_add(ir_node *node, ir_mode *mode)
34 {
35 dbg_info *dbgi = get_irn_dbg_info(node);
36 ir_node *block = get_nodes_block(node);
37 ir_node *left = get_Add_left(node);
38 ir_node *right = get_Add_right(node);
39 ir_node *left_low = get_lowered_low(left);
40 ir_node *left_high = get_lowered_high(left);
41 ir_node *right_low = get_lowered_low(right);
42 ir_node *right_high = get_lowered_high(right);
43 ir_node *addcc = new_bd_sparc_AddCC_t(dbgi, block, left_low,
44 right_low);
45 ir_node *res_low = new_r_Proj(addcc, mode_Iu, pn_sparc_AddCC_t_res);
46 ir_node *res_flags = new_r_Proj(addcc, mode_ANY, pn_sparc_AddCC_t_flags);
47 ir_node *addx = new_bd_sparc_AddX_t(dbgi, block, left_high,
48 right_high, res_flags, mode);
49 ir_set_dw_lowered(node, res_low, addx);
50 }
51
lower64_sub(ir_node * node,ir_mode * mode)52 static void lower64_sub(ir_node *node, ir_mode *mode)
53 {
54 dbg_info *dbgi = get_irn_dbg_info(node);
55 ir_node *block = get_nodes_block(node);
56 ir_node *left = get_Sub_left(node);
57 ir_node *right = get_Sub_right(node);
58 ir_node *left_low = get_lowered_low(left);
59 ir_node *left_high = get_lowered_high(left);
60 ir_node *right_low = get_lowered_low(right);
61 ir_node *right_high = get_lowered_high(right);
62 ir_node *subcc = new_bd_sparc_SubCC_t(dbgi, block, left_low,
63 right_low);
64 ir_node *res_low = new_r_Proj(subcc, mode_Iu, pn_sparc_SubCC_t_res);
65 ir_node *res_flags = new_r_Proj(subcc, mode_ANY, pn_sparc_SubCC_t_flags);
66 ir_node *subx = new_bd_sparc_SubX_t(dbgi, block, left_high,
67 right_high, res_flags, mode);
68 ir_set_dw_lowered(node, res_low, subx);
69 }
70
lower64_minus(ir_node * node,ir_mode * mode)71 static void lower64_minus(ir_node *node, ir_mode *mode)
72 {
73 dbg_info *dbgi = get_irn_dbg_info(node);
74 ir_graph *irg = get_irn_irg(node);
75 ir_node *block = get_nodes_block(node);
76 ir_node *op = get_Minus_op(node);
77 ir_node *right_low = get_lowered_low(op);
78 ir_node *right_high = get_lowered_high(op);
79 ir_mode *low_unsigned = get_irn_mode(right_low);
80 ir_node *left_low = new_r_Const(irg, get_mode_null(low_unsigned));
81 ir_node *left_high = new_r_Const(irg, get_mode_null(mode));
82 ir_node *subcc = new_bd_sparc_SubCC_t(dbgi, block, left_low,
83 right_low);
84 ir_node *res_low = new_r_Proj(subcc, mode_Iu, pn_sparc_SubCC_t_res);
85 ir_node *res_flags = new_r_Proj(subcc, mode_ANY, pn_sparc_SubCC_t_flags);
86 ir_node *subx = new_bd_sparc_SubX_t(dbgi, block, left_high,
87 right_high, res_flags, mode);
88 ir_set_dw_lowered(node, res_low, subx);
89 }
90
create_64_intrinsic_fkt(ir_type * method,const ir_op * op,const ir_mode * imode,const ir_mode * omode,void * context)91 static ir_entity *create_64_intrinsic_fkt(ir_type *method, const ir_op *op,
92 const ir_mode *imode,
93 const ir_mode *omode, void *context)
94 {
95 ir_type *glob = get_glob_type();
96 const char *name;
97 ident *id;
98 ir_entity *result;
99 (void) context;
100 (void) omode;
101
102 if (op == op_Mul) {
103 name = "__muldi3";
104 } else if (op == op_Div) {
105 name = mode_is_signed(imode) ? "__divdi3" : "__udivdi3";
106 } else if (op == op_Mod) {
107 name = mode_is_signed(imode) ? "__moddi3" : "__umoddi3";
108 } else if (op == op_Conv) {
109 if (mode_is_float(imode)) {
110 assert(get_mode_size_bits(omode) == 64);
111 if (get_mode_size_bits(imode) == 64) {
112 name = mode_is_signed(omode) ? "__fixdfdi" : "__fixunsdfdi";
113 } else if (get_mode_size_bits(imode) == 32) {
114 name = mode_is_signed(omode) ? "__fixsfdi" : "__fixunssfdi";
115 } else {
116 assert(get_mode_size_bits(imode) == 128);
117 panic("can't conver long double to long long yet");
118 }
119 } else if (mode_is_float(omode)) {
120 assert(get_mode_size_bits(imode) == 64);
121 if (get_mode_size_bits(omode) == 64) {
122 name = mode_is_signed(imode) ? "__floatdidf" : "__floatundidf";
123 } else if (get_mode_size_bits(omode) == 32) {
124 name = mode_is_signed(imode) ? "__floatdisf" : "__floatundisf";
125 } else {
126 assert(get_mode_size_bits(omode) == 128);
127 panic("can't convert long long to long double yet");
128 }
129 } else {
130 panic("can't lower 64bit Conv");
131 }
132 } else {
133 panic("Can't lower unexpected 64bit operation %s", get_op_name(op));
134 }
135 id = new_id_from_str(name);
136 result = new_entity(glob, id, method);
137 set_entity_ld_ident(result, id);
138 set_entity_visibility(result, ir_visibility_external);
139 return result;
140 }
141
sparc_lower_64bit(void)142 void sparc_lower_64bit(void)
143 {
144 lwrdw_param_t lower_dw_params = {
145 0, /* big endian */
146 64, /* doubleword size */
147 create_64_intrinsic_fkt,
148 NULL
149 };
150
151 /* make sure opcodes are initialized */
152 sparc_create_opcodes(&sparc_irn_ops);
153
154 ir_prepare_dw_lowering(&lower_dw_params);
155 ir_register_dw_lower_function(op_Add, lower64_add);
156 ir_register_dw_lower_function(op_Minus, lower64_minus);
157 ir_register_dw_lower_function(op_Sub, lower64_sub);
158 ir_lower_dw_ops();
159 }
160