2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief Sparc 64bit lowering
9 * @author Matthias Braun
13 #include "bearch_sparc_t.h"
15 #include "gen_sparc_new_nodes.h"
20 static void lower64_add(ir_node *node, ir_mode *mode)
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,
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);
39 static void lower64_sub(ir_node *node, ir_mode *mode)
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,
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);
58 static void lower64_minus(ir_node *node, ir_mode *mode)
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,
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);
78 static ir_entity *create_64_intrinsic_fkt(ir_type *method, const ir_op *op,
80 const ir_mode *omode, void *context)
82 ir_type *glob = get_glob_type();
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";
103 assert(get_mode_size_bits(imode) == 128);
104 panic("can't conver long double to long long yet");
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";
113 assert(get_mode_size_bits(omode) == 128);
114 panic("can't convert long long to long double yet");
117 panic("can't lower 64bit Conv");
120 panic("Can't lower unexpected 64bit operation %s", get_op_name(op));
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);
129 void sparc_lower_64bit(void)
131 lwrdw_param_t lower_dw_params = {
133 64, /* doubleword size */
134 create_64_intrinsic_fkt,
138 /* make sure opcodes are initialized */
139 sparc_create_opcodes(&sparc_irn_ops);
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);