ia32 isa implementation
[libfirm] / ir / be / ia32 / ia32_new_nodes.c
1 /**
2  * This file implements the creation of the achitecture specific firm opcodes
3  * and the coresponding node constructors for the $arch assembler irg.
4  * @author Christian Wuerdig
5  * $Id$
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <stdlib.h>
13
14 #include "irprog_t.h"
15 #include "irgraph_t.h"
16 #include "irnode_t.h"
17 #include "irmode_t.h"
18 #include "ircons_t.h"
19 #include "iropt_t.h"
20 #include "firm_common_t.h"
21 #include "irvrfy_t.h"
22
23 #include "../bearch.h"
24
25 #include "ia32_nodes_attr.h"
26 #include "ia32_new_nodes.h"
27
28 #include "gen_ia32_regalloc_if.c.inl"
29
30
31
32 /***********************************************************************************
33  *      _                                   _       _             __
34  *     | |                                 (_)     | |           / _|
35  *   __| |_   _ _ __ ___  _ __   ___ _ __   _ _ __ | |_ ___ _ __| |_ __ _  ___ ___
36  *  / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__|  _/ _` |/ __/ _ \
37  * | (_| | |_| | | | | | | |_) |  __/ |    | | | | | ||  __/ |  | || (_| | (_|  __/
38  *  \__,_|\__,_|_| |_| |_| .__/ \___|_|    |_|_| |_|\__\___|_|  |_| \__,_|\___\___|
39  *                       | |
40  *                       |_|
41  ***********************************************************************************/
42
43
44
45 /**
46  * Prints a tarval to file F.
47  * @param F         output file
48  * @param tv        tarval
49  * @param brackets  1 == print square brackets around tarval
50  */
51 static void fprintf_tv(FILE *F, tarval *tv, int brackets) {
52   char buf[1024];
53   tarval_snprintf(buf, sizeof(buf), tv);
54
55   if (brackets)
56     fprintf(F, "[%s]", buf);
57   else
58     fprintf(F, "%s", buf);
59 }
60
61 /**
62  * Returns the name of a SymConst.
63  * @param symc  the SymConst
64  * @return name of the SymConst
65  */
66 const char *get_sc_name(ir_node *symc) {
67   if (get_irn_opcode(symc) != iro_SymConst)
68     return "NONE";
69
70   switch (get_SymConst_kind(symc)) {
71     case symconst_addr_name:
72       return get_id_str(get_SymConst_name(symc));
73
74     case symconst_addr_ent:
75       return get_entity_ld_name(get_SymConst_entity(symc));
76
77     default:
78       assert(0 && "Unsupported SymConst");
79   }
80 }
81
82 /**
83  * Dumper interface for dumping ia32 nodes in vcg.
84  * @param n        the node to dump
85  * @param F        the output file
86  * @param reason   indicates which kind of information should be dumped
87  * @return 0 on success or != 0 on failure
88  */
89 static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
90   const char *name, *p;
91   ir_mode    *mode = NULL;
92   int        bad   = 0;
93
94   switch (reason) {
95     case dump_node_opcode_txt:
96       name = get_irn_opname(n);
97       fprintf(F, "%s", name);
98       break;
99
100     case dump_node_mode_txt:
101       mode = get_irn_mode(n);
102
103       if (mode == mode_BB || mode == mode_ANY || mode == mode_BAD || mode == mode_T) {
104         mode = NULL;
105       }
106       else if (is_ia32_Load(n)) {
107         mode = get_irn_mode(get_irn_n(n, 1));
108       }
109       else if (is_ia32_Store(n)) {
110         mode = get_irn_mode(get_irn_n(n, 2));
111       }
112
113       if (mode)
114         fprintf(F, "[%s]", get_mode_name(mode));
115       break;
116
117     case dump_node_nodeattr_txt:
118       name = get_irn_opname(n);
119       p = name + strlen(name) - 2;
120       if (p[0] == '_' && p[1] == 'i') {
121         tarval *tv = get_ia32_Immop_tarval(n);
122         if (tv)
123           fprintf_tv(F, tv, 1);
124         else {
125           fprintf(F, "[SymC &%s]", get_sc_name(get_ia32_old_ir(n)));
126         }
127       }
128       else if (is_ia32_Call(n)) {
129         ir_node *old_call = get_ia32_old_ir(n);
130         ir_node *sc       = get_Call_ptr(old_call);
131
132         fprintf(F, "&%s ", get_sc_name(sc));
133       }
134       break;
135
136     case dump_node_info_txt:
137       if (is_ia32_Lea(n)) {
138         tarval *o  = get_ia32_offs(n);
139         tarval *tv = get_ia32_Immop_tarval(n);
140
141         fprintf(F, "LEA ");
142         if (o)
143           fprintf_tv(F, o, 0);
144         fprintf(F, "(%s, %s", get_irn_opname(get_irn_n(n, 0)), get_irn_opname(get_irn_n(n, 1)));
145         if (tv) {
146           fprintf(F, ", ");
147           fprintf_tv(F, tv, 0);
148         }
149         fprintf(F, ")\n");
150       }
151       break;
152   }
153
154   return bad;
155 }
156
157
158
159 /***************************************************************************************************
160  *        _   _                   _       __        _                    _   _               _
161  *       | | | |                 | |     / /       | |                  | | | |             | |
162  *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
163  *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
164  * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
165  *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
166  *                                        __/ |
167  *                                       |___/
168  ***************************************************************************************************/
169
170 /**
171  * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
172  * Firm was made by people hating const :-(
173  */
174 asmop_attr *get_ia32_attr(const ir_node *node) {
175   return (asmop_attr *)get_irn_generic_attr((ir_node *)node);
176 }
177
178 /**
179  * Return the tarval of an immediate operation or NULL in case of SymConst
180  */
181 tarval *get_ia32_Immop_tarval(const ir_node *node) {
182   asmop_attr *attr = get_ia32_attr(node);
183   if (attr->tp == asmop_Const)
184     return attr->tv;
185   else
186     return NULL;
187 }
188
189 /**
190  * Return the old_ir attribute.
191  */
192 ir_node *get_ia32_old_ir(const ir_node *node) {
193   asmop_attr *attr = get_ia32_attr(node);
194   return attr->old_ir;
195 }
196
197 /**
198  * Copy the attributes from an ia32_Const to an Immop (Add_i, Sub_i, ...) node
199  */
200 void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) {
201   asmop_attr *na = get_ia32_attr(node);
202   asmop_attr *ca = get_ia32_attr(cnst);
203
204   assert(is_ia32_Const(cnst) && "Need ia32_Const to set Immop attr");
205
206   na->tp     = ca->tp;
207   na->tv     = ca->tv;
208   na->old_ir = ca->old_ir;
209 }
210
211 /**
212  * Copy the attributes from a Const to an ia32_Const
213  */
214 void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
215   asmop_attr *attr = get_ia32_attr(ia32_cnst);
216
217   assert(is_ia32_Const(ia32_cnst) && "Need ia32_Const to set Const attr");
218
219   switch (get_irn_opcode(cnst)) {
220     case iro_Const:
221       attr->tp = asmop_Const;
222       attr->tv = get_Const_tarval(cnst);
223       break;
224     case iro_SymConst:
225       attr->tp     = asmop_SymConst;
226       attr->old_ir = cnst;
227       break;
228     case iro_Unknown:
229       assert(0 && "Unknown Const NYI");
230       break;
231     default:
232       assert(0 && "Cannot create ia32_Const for this opcode");
233   }
234 }
235
236 /**
237  * Sets the type of an ia32_Const.
238  */
239 void set_ia32_Const_type(ir_node *node, int type) {
240   asmop_attr *attr   = get_ia32_attr(node);
241
242   assert(is_ia32_Const(node) && "Need ia32_Const to set type");
243   assert((type == asmop_Const || type == asmop_SymConst) && "Unsupported ia32_Const type");
244
245   attr->tp = type;
246 }
247
248 /**
249  * Sets the attributes of an immediate operation to the specified tarval
250  */
251 void set_ia32_Immop_tarval(ir_node *node, tarval *tv) {
252   asmop_attr *attr = get_ia32_attr(node);
253
254   attr->tp = asmop_Const;
255   attr->tv = tv;
256 }
257
258 /**
259  * Sets the offset for a Lea.
260  */
261 void set_ia32_offs(ir_node *node, tarval *offs) {
262   asmop_attr *attr = get_ia32_attr(node);
263   attr->offset     = offs;
264 }
265
266 /**
267  * Gets the offset for a Lea.
268  */
269 tarval *get_ia32_offs(const ir_node *node) {
270   asmop_attr *attr = get_ia32_attr(node);
271   return attr->offset;
272 }
273
274 /**
275  * Returns the argument register requirements of an ia32 node.
276  */
277 const arch_register_req_t **get_ia32_in_req(const ir_node *node) {
278   asmop_attr *attr = get_ia32_attr(node);
279   return attr->in_req;
280 }
281
282 /**
283  * Returns the result register requirements of an ia32 node.
284  */
285 const arch_register_req_t **get_ia32_out_req(const ir_node *node) {
286   asmop_attr *attr = get_ia32_attr(node);
287   return attr->out_req;
288 }
289
290 /**
291  * Returns the register flag of an ia32 node.
292  */
293 arch_irn_flags_t get_ia32_flags(const ir_node *node) {
294   asmop_attr *attr = get_ia32_attr(node);
295   return attr->flags;
296 }
297
298 /**
299  * Returns the argument register slots of an ia32 node.
300  */
301 const arch_register_t **get_ia32_in_slots(const ir_node *node) {
302   asmop_attr *attr = get_ia32_attr(node);
303   return attr->in;
304 }
305
306 /**
307  * Returns the result register slots of an ia32 node.
308  */
309 const arch_register_t **get_ia32_out_slots(const ir_node *node) {
310   asmop_attr *attr = get_ia32_attr(node);
311   return attr->out;
312 }
313
314 /**
315  * Returns the name of the IN register at position pos.
316  */
317 const char *get_ia32_in_reg_name(const ir_node *node, int pos) {
318   asmop_attr *attr = get_ia32_attr(node);
319
320   assert(is_ia32_irn(node) && "Not an ia32 node.");
321   assert(pos < get_irn_arity(node) && "Invalid IN position.");
322
323   return attr->in[pos]->name;
324 }
325
326 /**
327  * Returns the name of the OUT register at position pos.
328  */
329 const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
330   asmop_attr *attr = get_ia32_attr(node);
331
332   assert(is_ia32_irn(node) && "Not an ia32 node.");
333   assert(pos < attr->n_res && "Invalid OUT position.");
334
335   return attr->out[pos]->name;
336 }
337
338 /**
339  * Returns the index of the IN register at position pos within its register class.
340  */
341 int get_ia32_in_regnr(const ir_node *node, int pos) {
342   asmop_attr *attr = get_ia32_attr(node);
343
344   assert(is_ia32_irn(node) && "Not an ia32 node.");
345   assert(pos < get_irn_arity(node) && "Invalid IN position.");
346
347   return attr->in[pos]->index;
348 }
349
350 /**
351  * Returns the index of the OUT register at position pos within its register class.
352  */
353 int get_ia32_out_regnr(const ir_node *node, int pos) {
354   asmop_attr *attr = get_ia32_attr(node);
355
356   assert(is_ia32_irn(node) && "Not an ia32 node.");
357   assert(pos < attr->n_res && "Invalid OUT position.");
358
359   return attr->out[pos]->index;
360 }
361
362 /**
363  * Sets the number of results.
364  */
365 void set_ia32_n_res(ir_node *node, int n_res) {
366   asmop_attr *attr = get_ia32_attr(node);
367   attr->n_res = n_res;
368 }
369
370 /**
371  * Returns the number of results.
372  */
373 int get_ia32_n_res(const ir_node *node) {
374   asmop_attr *attr = get_ia32_attr(node);
375   return attr->n_res;
376 }
377
378 /**
379  * Sets the flavour of an ia32 DivMod node to flavour_Div/Mod/DivMod.
380  */
381 void set_ia32_DivMod_flavour(ir_node *node, divmod_flavour_t dm_flav) {
382   asmop_attr *attr = get_ia32_attr(node);
383   attr->dm_flav    = dm_flav;
384 }
385
386 /* Include the generated functions */
387 #include "gen_ia32_new_nodes.c.inl"