initial version of dword support for ia32
[libfirm] / ir / be / ia32 / ia32_intrinsics.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include "irop.h"
6 #include "irnode_t.h"
7 #include "ircons.h"
8 #include "irprog_t.h"
9 #include "lower_intrinsics.h"
10 #include "lower_dw.h"
11 #include "mangle.h"
12 #include "array.h"
13
14 /** The array of all intrinsics that must be mapped. */
15 static i_record *intrinsics;
16
17 /** An array to cache all entities */
18 static entity *i_ents[iro_MaxOpcode];
19
20 /**
21  * Maps all intrinsic calls that the backend support
22  * and map all instructions the backend did not support
23  * to runtime calls.
24  */
25 void ia32_handle_intrinsics(void) {
26         if (intrinsics && ARR_LEN(intrinsics) > 0)
27                 lower_intrinsics(intrinsics, ARR_LEN(intrinsics));
28 }
29
30 #define BINOP_Left_Low   0
31 #define BINOP_Left_High  1
32 #define BINOP_Right_Low  2
33 #define BINOP_Right_High 3
34
35 /**
36  * Map an Add (a_l, a_h, b_l, b_h)
37  */
38 static int map_Add(ir_node *call, void *ctx) {
39         ir_graph *irg = current_ir_graph;
40         ir_node *block = get_nodes_block(call);
41         ir_node **params = get_Call_param_arr(call);
42         ir_node *l_res, *h_res, *res, *in[2];
43         ir_node *a_l = params[0];
44         ir_node *a_h = params[1];
45         ir_node *b_l = params[2];
46         ir_node *b_h = params[3];
47
48         /* l_res = a_l + b_l */
49         /* h_res = a_h + b_h + carry */
50
51         in[0] = l_res;
52         in[1] = h_res;
53         res = new_r_Tuple(irg, block, 2, in);
54
55         turn_into_tuple(call, pn_Call_max);
56         set_Tuple_pred(call, pn_Call_M_regular,        get_irg_no_mem(irg));
57         set_Tuple_pred(call, pn_Call_X_except,         get_irg_bad(irg));
58         set_Tuple_pred(call, pn_Call_T_result,         res);
59         set_Tuple_pred(call, pn_Call_M_except,         get_irg_bad(irg));
60         set_Tuple_pred(call, pn_Call_P_value_res_base, get_irg_bad(irg));
61
62         return 1;
63 }
64
65 /**
66  * Map a Sub (a_l, a_h, b_l, b_h)
67  */
68 static int map_Sub(ir_node *call, void *ctx) {
69         ir_graph *irg = current_ir_graph;
70         ir_node *block = get_nodes_block(call);
71         ir_node **params = get_Call_param_arr(call);
72         ir_node *l_res, *h_res, *res, *in[2];
73         ir_node *a_l = params[0];
74         ir_node *a_h = params[1];
75         ir_node *b_l = params[2];
76         ir_node *b_h = params[3];
77
78         /* l_res = a_l - b_l */
79         /* h_res = a_h - b_h - carry */
80
81         in[0] = l_res;
82         in[1] = h_res;
83         res = new_r_Tuple(irg, block, 2, in);
84
85         turn_into_tuple(call, pn_Call_max);
86         set_Tuple_pred(call, pn_Call_M_regular,        get_irg_no_mem(irg));
87         set_Tuple_pred(call, pn_Call_X_except,         get_irg_bad(irg));
88         set_Tuple_pred(call, pn_Call_T_result,         res);
89         set_Tuple_pred(call, pn_Call_M_except,         get_irg_bad(irg));
90         set_Tuple_pred(call, pn_Call_P_value_res_base, get_irg_bad(irg));
91
92         return 1;
93 }
94
95 /**
96  * Ia32 implementation.
97  *
98  * @param method   the method type of the emulation function entity
99  * @param op       the emulated ir_op
100  * @param imode    the input mode of the emulated opcode
101  * @param omode    the output mode of the emulated opcode
102  * @param context  the context parameter
103  */
104 entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
105                                   const ir_mode *imode, const ir_mode *omode,
106                                   void *context)
107 {
108         i_record      elt;
109         entity        **ent = NULL;
110         i_mapper_func mapper;
111
112         if (! intrinsics)
113                 intrinsics = NEW_ARR_F(i_record, 0);
114
115         switch (get_op_code(op)) {
116         case iro_Add:
117                 ent    = &i_ents[iro_Add];
118                 mapper = map_Add;
119                 break;
120         case iro_Sub:
121                 ent    = &i_ents[iro_Sub];
122                 mapper = map_Sub;
123                 break;
124         default:
125                 return def_create_intrinsic_fkt(method, op, imode, omode, context);
126         }
127
128         if (ent && ! *ent) {
129 #define IDENT(s)  new_id_from_chars(s, sizeof(s)-1)
130
131                 ident *id = mangle(IDENT("L"), get_op_name(op));
132                 *ent = new_entity(get_glob_type(), id, method);
133         }
134
135         elt.i_call.kind     = INTRINSIC_CALL;
136         elt.i_call.i_ent    = *ent;
137         elt.i_call.i_mapper = mapper;
138         elt.i_call.ctx      = NULL;
139         elt.i_call.link     = NULL;
140
141         ARR_APP1(i_record, intrinsics, elt);
142 }