besched: Change sched_foreach_from(sched_next(x), y) to sched_foreach_after(x, y).
[libfirm] / ir / be / sparc / sparc_lower64.c
1 /*
2  * This file is part of libFirm.
3  * Copyright (C) 2012 University of Karlsruhe.
4  */
5
6 /**
7  * @file
8  * @brief    Sparc 64bit lowering
9  * @author   Matthias Braun
10  */
11 #include "config.h"
12
13 #include "bearch_sparc_t.h"
14 #include "error.h"
15 #include "gen_sparc_new_nodes.h"
16 #include "lower_dw.h"
17 #include "ircons_t.h"
18 #include "util.h"
19
20 static void lower64_add(ir_node *node, ir_mode *mode)
21 {
22         dbg_info *dbgi       = get_irn_dbg_info(node);
23         ir_node  *block      = get_nodes_block(node);
24         ir_node  *left       = get_Add_left(node);
25         ir_node  *right      = get_Add_right(node);
26         ir_node  *left_low   = get_lowered_low(left);
27         ir_node  *left_high  = get_lowered_high(left);
28         ir_node  *right_low  = get_lowered_low(right);
29         ir_node  *right_high = get_lowered_high(right);
30         ir_node  *addcc      = new_bd_sparc_AddCC_t(dbgi, block, left_low,
31                                                     right_low);
32         ir_node  *res_low    = new_r_Proj(addcc, mode_Iu, pn_sparc_AddCC_t_res);
33         ir_node  *res_flags  = new_r_Proj(addcc, mode_ANY, pn_sparc_AddCC_t_flags);
34         ir_node  *addx       = new_bd_sparc_AddX_t(dbgi, block, left_high,
35                                                    right_high, res_flags, mode);
36         ir_set_dw_lowered(node, res_low, addx);
37 }
38
39 static void lower64_sub(ir_node *node, ir_mode *mode)
40 {
41         dbg_info *dbgi       = get_irn_dbg_info(node);
42         ir_node  *block      = get_nodes_block(node);
43         ir_node  *left       = get_Sub_left(node);
44         ir_node  *right      = get_Sub_right(node);
45         ir_node  *left_low   = get_lowered_low(left);
46         ir_node  *left_high  = get_lowered_high(left);
47         ir_node  *right_low  = get_lowered_low(right);
48         ir_node  *right_high = get_lowered_high(right);
49         ir_node  *subcc      = new_bd_sparc_SubCC_t(dbgi, block, left_low,
50                                                     right_low);
51         ir_node  *res_low    = new_r_Proj(subcc, mode_Iu, pn_sparc_SubCC_t_res);
52         ir_node  *res_flags  = new_r_Proj(subcc, mode_ANY, pn_sparc_SubCC_t_flags);
53         ir_node  *subx       = new_bd_sparc_SubX_t(dbgi, block, left_high,
54                                                    right_high, res_flags, mode);
55         ir_set_dw_lowered(node, res_low, subx);
56 }
57
58 static void lower64_minus(ir_node *node, ir_mode *mode)
59 {
60         dbg_info *dbgi         = get_irn_dbg_info(node);
61         ir_graph *irg          = get_irn_irg(node);
62         ir_node  *block        = get_nodes_block(node);
63         ir_node  *op           = get_Minus_op(node);
64         ir_node  *right_low    = get_lowered_low(op);
65         ir_node  *right_high   = get_lowered_high(op);
66         ir_mode  *low_unsigned = get_irn_mode(right_low);
67         ir_node  *left_low     = new_r_Const(irg, get_mode_null(low_unsigned));
68         ir_node  *left_high    = new_r_Const(irg, get_mode_null(mode));
69         ir_node  *subcc        = new_bd_sparc_SubCC_t(dbgi, block, left_low,
70                                                       right_low);
71         ir_node  *res_low      = new_r_Proj(subcc, mode_Iu, pn_sparc_SubCC_t_res);
72         ir_node  *res_flags    = new_r_Proj(subcc, mode_ANY, pn_sparc_SubCC_t_flags);
73         ir_node  *subx         = new_bd_sparc_SubX_t(dbgi, block, left_high,
74                                                      right_high, res_flags, mode);
75         ir_set_dw_lowered(node, res_low, subx);
76 }
77
78 static ir_entity *create_64_intrinsic_fkt(ir_type *method, const ir_op *op,
79                                           const ir_mode *imode,
80                                           const ir_mode *omode, void *context)
81 {
82         ir_type    *glob = get_glob_type();
83         const char *name;
84         ident      *id;
85         ir_entity  *result;
86         (void) context;
87         (void) omode;
88
89         if (op == op_Mul) {
90                 name = "__muldi3";
91         } else if (op == op_Div) {
92                 name = mode_is_signed(imode) ? "__divdi3" : "__udivdi3";
93         } else if (op == op_Mod) {
94                 name = mode_is_signed(imode) ? "__moddi3" : "__umoddi3";
95         } else if (op == op_Conv) {
96                 if (mode_is_float(imode)) {
97                         assert(get_mode_size_bits(omode) == 64);
98                         if (get_mode_size_bits(imode) == 64) {
99                                 name = mode_is_signed(omode) ? "__fixdfdi" : "__fixunsdfdi";
100                         } else if (get_mode_size_bits(imode) == 32) {
101                                 name = mode_is_signed(omode) ? "__fixsfdi" : "__fixunssfdi";
102                         } else {
103                                 assert(get_mode_size_bits(imode) == 128);
104                                 panic("can't conver long double to long long yet");
105                         }
106                 } else if (mode_is_float(omode)) {
107                         assert(get_mode_size_bits(imode) == 64);
108                         if (get_mode_size_bits(omode) == 64) {
109                                 name = mode_is_signed(imode) ? "__floatdidf" : "__floatundidf";
110                         } else if (get_mode_size_bits(omode) == 32) {
111                                 name = mode_is_signed(imode) ? "__floatdisf" : "__floatundisf";
112                         } else {
113                                 assert(get_mode_size_bits(omode) == 128);
114                                 panic("can't convert long long to long double yet");
115                         }
116                 } else {
117                         panic("can't lower 64bit Conv");
118                 }
119         } else {
120                 panic("Can't lower unexpected 64bit operation %s", get_op_name(op));
121         }
122         id     = new_id_from_str(name);
123         result = new_entity(glob, id, method);
124         set_entity_ld_ident(result, id);
125         set_entity_visibility(result, ir_visibility_external);
126         return result;
127 }
128
129 void sparc_lower_64bit(void)
130 {
131         lwrdw_param_t lower_dw_params = {
132                 0,  /* big endian */
133                 64, /* doubleword size */
134                 create_64_intrinsic_fkt,
135                 NULL
136         };
137
138         /* make sure opcodes are initialized */
139         sparc_create_opcodes(&sparc_irn_ops);
140
141         ir_prepare_dw_lowering(&lower_dw_params);
142         ir_register_dw_lower_function(op_Add,   lower64_add);
143         ir_register_dw_lower_function(op_Minus, lower64_minus);
144         ir_register_dw_lower_function(op_Sub,   lower64_sub);
145         ir_lower_dw_ops();
146 }