added gen of new ops
[libfirm] / ir / be / ia32 / transform.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include "irnode_t.h"
6 #include "irgraph_t.h"
7 #include "irmode_t.h"
8 #include "irgmod.h"
9 #include "dbginfo.h"
10 #include "irop_t.h"
11 #include "debug.h"
12
13 #include "../firm2arch_nodes_attr.h"
14 #include "../bearch_firm.h"
15 #include "transform.h"
16 #include "new_nodes.h"
17
18 /* determine if one operator is an Imm */
19 ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
20   if (op1)
21     return is_Imm(op1) ? op1 : (is_Imm(op2) ? op2 : NULL);
22   else return is_Imm(op2) ? op2 : NULL;
23 }
24
25 /* determine if one operator is not an Imm */
26 ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
27   return !is_Imm(op1) ? op1 : (!is_Imm(op2) ? op2 : NULL);
28 }
29
30
31
32 /**
33  * Creates an ia32 Add with immediate.
34  *
35  * @param dbg       firm dbg
36  * @param block     the block the new node should belong to
37  * @param expr_op   operator
38  * @param mode      node mode
39  * @return the created ia23 Add_i node
40  */
41 ir_node *gen_imm_Add(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
42   return new_rd_ia32_Add_i(dbg, current_ir_graph, block, expr_op, mode);
43 }
44
45 /**
46  * Creates an ia32 Add.
47  *
48  * @param dbg       firm node dbg
49  * @param block     the block the new node should belong to
50  * @param op1       first operator
51  * @param op2       second operator
52  * @param mode      node mode
53  * @return the created ia32 Add node
54  */
55 ir_node *gen_Add(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
56   return new_rd_ia32_Add(dbg, current_ir_graph, block, op1, op2, mode);
57 }
58
59
60
61 /**
62  * Creates an ia32 Mul with immediate.
63  *
64  * @param dbg       firm dbg
65  * @param block     the block the new node should belong to
66  * @param expr_op   operator
67  * @param mode      node mode
68  * @return the created ia23 Mul_i node
69  */
70 ir_node *gen_imm_Mul(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
71   return new_rd_ia32_Mul_i(dbg, current_ir_graph, block, expr_op, mode);
72 }
73
74 /**
75  * Creates an ia32 Mul.
76  *
77  * @param dbg       firm node dbg
78  * @param block     the block the new node should belong to
79  * @param op1       first operator
80  * @param op2       second operator
81  * @param mode      node mode
82  * @return the created ia32 Mul node
83  */
84 ir_node *gen_Mul(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
85   return new_rd_ia32_Mul(dbg, current_ir_graph, block, op1, op2, mode);
86 }
87
88
89
90 /**
91  * Creates an ia32 And with immediate.
92  *
93  * @param dbg       firm dbg
94  * @param block     the block the new node should belong to
95  * @param expr_op   operator
96  * @param mode      node mode
97  * @return the created ia23 And_i node
98  */
99 ir_node *gen_imm_And(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
100   return new_rd_ia32_And_i(dbg, current_ir_graph, block, expr_op, mode);
101 }
102
103 /**
104  * Creates an ia32 And.
105  *
106  * @param dbg       firm node dbg
107  * @param block     the block the new node should belong to
108  * @param op1       first operator
109  * @param op2       second operator
110  * @param mode      node mode
111  * @return the created ia32 And node
112  */
113 ir_node *gen_And(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
114   return new_rd_ia32_And(dbg, current_ir_graph, block, op1, op2, mode);
115 }
116
117
118
119 /**
120  * Creates an ia32 Or with immediate.
121  *
122  * @param dbg       firm dbg
123  * @param block     the block the new node should belong to
124  * @param expr_op   operator
125  * @param mode      node mode
126  * @return the created ia23 Or_i node
127  */
128 ir_node *gen_imm_Or(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
129   return new_rd_ia32_Or_i(dbg, current_ir_graph, block, expr_op, mode);
130 }
131
132 /**
133  * Creates an ia32 Or.
134  *
135  * @param dbg       firm node dbg
136  * @param block     the block the new node should belong to
137  * @param op1       first operator
138  * @param op2       second operator
139  * @param mode      node mode
140  * @return the created ia32 Or node
141  */
142 ir_node *gen_Or(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
143   return new_rd_ia32_Or(dbg, current_ir_graph, block, op1, op2, mode);
144 }
145
146
147
148 /**
149  * Creates an ia32 Eor with immediate.
150  *
151  * @param dbg       firm dbg
152  * @param block     the block the new node should belong to
153  * @param expr_op   operator
154  * @param mode      node mode
155  * @return the created ia23 Eor_i node
156  */
157 ir_node *gen_imm_Eor(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
158   return new_rd_ia32_Eor_i(dbg, current_ir_graph, block, expr_op, mode);
159 }
160
161 /**
162  * Creates an ia32 Eor.
163  *
164  * @param dbg       firm node dbg
165  * @param block     the block the new node should belong to
166  * @param op1       first operator
167  * @param op2       second operator
168  * @param mode      node mode
169  * @return the created ia32 Eor node
170  */
171 ir_node *gen_Eor(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
172   return new_rd_ia32_Eor(dbg, current_ir_graph, block, op1, op2, mode);
173 }
174
175
176
177 /**
178  * Creates an ia32 Cmp with immediate.
179  *
180  * @param dbg       firm dbg
181  * @param block     the block the new node should belong to
182  * @param expr_op   operator
183  * @param mode      node mode
184  * @return the created ia23 Cmp_i node
185  */
186 ir_node *gen_imm_Cmp(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
187   return new_rd_ia32_Cmp_i(dbg, current_ir_graph, block, expr_op, mode);
188 }
189
190 /**
191  * Creates an ia32 Cmp.
192  *
193  * @param dbg       firm node dbg
194  * @param block     the block the new node should belong to
195  * @param op1       first operator
196  * @param op2       second operator
197  * @param mode      node mode
198  * @return the created ia32 Cmp node
199  */
200 ir_node *gen_Cmp(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
201   return new_rd_ia32_Cmp(dbg, current_ir_graph, block, op1, op2, mode);
202 }
203
204
205
206 /**
207  * Creates an ia32 Sub with immediate.
208  *
209  * @param dbg       firm dbg
210  * @param block     the block the new node should belong to
211  * @param expr_op   operator
212  * @param mode      node mode
213  * @return the created ia23 Sub_i node
214  */
215 ir_node *gen_imm_Sub(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
216   return new_rd_ia32_Sub_i(dbg, current_ir_graph, block, expr_op, mode);
217 }
218
219 /**
220  * Creates an ia32 Sub.
221  *
222  * @param dbg       firm node dbg
223  * @param block     the block the new node should belong to
224  * @param op1       first operator
225  * @param op2       second operator
226  * @param mode      node mode
227  * @return the created ia32 Sub node
228  */
229 ir_node *gen_Sub(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
230   return new_rd_ia32_Sub(dbg, current_ir_graph, block, op1, op2, mode);
231 }
232
233
234
235 /**
236  * Creates an ia32 Mod with immediate.
237  *
238  * @param dbg       firm dbg
239  * @param block     the block the new node should belong to
240  * @param expr_op   operator
241  * @param mode      node mode
242  * @return the created ia23 Mod_i node
243  */
244 ir_node *gen_imm_Mod(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
245   return new_rd_ia32_Mod_i(dbg, current_ir_graph, block, expr_op, mode);
246 }
247
248 /**
249  * Creates an ia32 Mod.
250  *
251  * @param dbg       firm node dbg
252  * @param block     the block the new node should belong to
253  * @param op1       first operator
254  * @param op2       second operator
255  * @param mode      node mode
256  * @return the created ia32 Mod node
257  */
258 ir_node *gen_Mod(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
259   return new_rd_ia32_Mod(dbg, current_ir_graph, block, op1, op2, mode);
260 }
261
262
263
264 /**
265  * Creates an ia32 Shl with immediate.
266  *
267  * @param dbg       firm dbg
268  * @param block     the block the new node should belong to
269  * @param expr_op   operator
270  * @param mode      node mode
271  * @return the created ia23 Shl_i node
272  */
273 ir_node *gen_imm_Shl(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
274   return new_rd_ia32_Shl_i(dbg, current_ir_graph, block, expr_op, mode);
275 }
276
277 /**
278  * Creates an ia32 Shl.
279  *
280  * @param dbg       firm node dbg
281  * @param block     the block the new node should belong to
282  * @param op1       first operator
283  * @param op2       second operator
284  * @param mode      node mode
285  * @return the created ia32 Shl node
286  */
287 ir_node *gen_Shl(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
288   return new_rd_ia32_Shl(dbg, current_ir_graph, block, op1, op2, mode);
289 }
290
291
292
293 /**
294  * Creates an ia32 Shr with immediate.
295  *
296  * @param dbg       firm dbg
297  * @param block     the block the new node should belong to
298  * @param expr_op   operator
299  * @param mode      node mode
300  * @return the created ia23 Shr_i node
301  */
302 ir_node *gen_imm_Shr(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
303   return new_rd_ia32_Shr_i(dbg, current_ir_graph, block, expr_op, mode);
304 }
305
306 /**
307  * Creates an ia32 Shr.
308  *
309  * @param dbg       firm node dbg
310  * @param block     the block the new node should belong to
311  * @param op1       first operator
312  * @param op2       second operator
313  * @param mode      node mode
314  * @return the created ia32 Shr node
315  */
316 ir_node *gen_Shr(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
317   return new_rd_ia32_Shr(dbg, current_ir_graph, block, op1, op2, mode);
318 }
319
320
321
322 /**
323  * Creates an ia32 Shrs with immediate.
324  *
325  * @param dbg       firm dbg
326  * @param block     the block the new node should belong to
327  * @param expr_op   operator
328  * @param mode      node mode
329  * @return the created ia23 Shrs_i node
330  */
331 ir_node *gen_imm_Shrs(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
332   return new_rd_ia32_Shrs_i(dbg, current_ir_graph, block, expr_op, mode);
333 }
334
335 /**
336  * Creates an ia32 Shrs.
337  *
338  * @param dbg       firm node dbg
339  * @param block     the block the new node should belong to
340  * @param op1       first operator
341  * @param op2       second operator
342  * @param mode      node mode
343  * @return the created ia32 Shrs node
344  */
345 ir_node *gen_Shrs(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
346   return new_rd_ia32_Shrs(dbg, current_ir_graph, block, op1, op2, mode);
347 }
348
349
350
351 /**
352  * Creates an ia32 Rot with immediate.
353  *
354  * @param dbg       firm dbg
355  * @param block     the block the new node should belong to
356  * @param expr_op   operator
357  * @param mode      node mode
358  * @return the created ia23 Rot_i node
359  */
360 ir_node *gen_imm_Rot(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
361   return new_rd_ia32_Rot_i(dbg, current_ir_graph, block, expr_op, mode);
362 }
363
364 /**
365  * Creates an ia32 Rot.
366  *
367  * @param dbg       firm node dbg
368  * @param block     the block the new node should belong to
369  * @param op1       first operator
370  * @param op2       second operator
371  * @param mode      node mode
372  * @return the created ia32 Rot node
373  */
374 ir_node *gen_Rot(dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
375   return new_rd_ia32_Rot(dbg, current_ir_graph, block, op1, op2, mode);
376 }
377
378
379
380 /**
381  * Transforms a Conv node.
382  *
383  * @param mod     the debug module
384  * @param block   the block the new node should belong to
385  * @param node    the ir Conv node
386  * @param op      operator
387  * @param mode    node mode
388  * @return the created ia32 Conv node
389  */
390 ir_node *gen_Conv(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) {
391   return new_rd_ia32_Conv(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
392 }
393
394
395
396 /**
397  * Transforms commutative operations (op_Add, op_Mul, op_And, op_Or, op_Eor, op_Cmp)
398  * and non-commutative operations with com == 0 (op_Sub, op_Mod, op_Shl, op_Shr, op_Shrs, op_Rot)
399  *
400  * @param mod       the debug module
401  * @param block     the block node belongs to
402  * @param node      the node to transform
403  * @param op1       first operator
404  * @param op2       second operator
405  * @param mode      node mode
406  * @param com       flag if op is commutative
407  * @return the created assembler node
408  */
409 ir_node *gen_arith_Op(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op1, ir_node *op2, ir_mode *mode, int com) {
410   dbg_info *dbg     = get_irn_dbg_info(node);
411   ir_node *imm_op   = NULL;
412   ir_node *expr_op  = NULL;
413   ir_node *asm_node = NULL;
414
415 #define GENOP(a)  case iro_##a: asm_node = gen_##a(dbg, block, op1, op2, mode); break
416 #define GENOPI(a) case iro_##a: asm_node = gen_imm_##a(dbg, block, expr_op, mode); break
417
418   if (com)
419     imm_op  = get_immediate_op(op1, op2);
420   else
421     imm_op  = get_immediate_op(NULL, op2);
422
423   expr_op = get_expr_op(op1, op2);
424
425   /* TODO: Op(Imm, Imm) support */
426   if (is_Imm(op1) && is_Imm(op2)) {
427     DBG((mod, LEVEL_1, "found unexpected %s(Imm, Imm), creating binop ... ", get_irn_opname(node)));
428     imm_op = NULL;
429   }
430
431   DBG((mod, LEVEL_1, "(op1: %s -- op2: %s) ... ", get_irn_opname(op1), get_irn_opname(op2)));
432
433   if (imm_op) {
434     imm_attr_t *attr_imm = (imm_attr_t *)get_irn_generic_attr(imm_op);
435
436     DBG((mod, LEVEL_1, "%s with imm ... ", get_irn_opname(node)));
437
438     /* make sure that Imm is a Const and no SymConst */
439     if (attr_imm->tp == imm_Const) {
440       switch(get_irn_opcode(node)) {
441         GENOPI(Add);
442         GENOPI(Mul);
443         GENOPI(And);
444         GENOPI(Or);
445         GENOPI(Eor);
446         GENOPI(Cmp);
447
448         GENOPI(Sub);
449         GENOPI(Mod);
450         GENOPI(Shl);
451         GENOPI(Shr);
452         GENOPI(Shrs);
453         GENOPI(Rot);
454         default:
455           assert("binop_i: THIS SHOULD NOT HAPPEN");
456       }
457
458       /* make the Const an attribute */
459       asmop_attr *attr = (asmop_attr *)get_irn_generic_attr(asm_node);
460       attr->tv = attr_imm->data.tv;
461     } /* TODO: SymConst support */
462     else
463       goto do_binop;
464   }
465   else {
466 do_binop:
467     DBG((mod, LEVEL_1, "%s as binop ... ", get_irn_opname(node)));
468
469     switch(get_irn_opcode(node)) {
470       GENOP(Add);
471       GENOP(Mul);
472       GENOP(And);
473       GENOP(Or);
474       GENOP(Eor);
475       GENOP(Cmp);
476
477       GENOP(Sub);
478       GENOP(Mod);
479       GENOP(Shl);
480       GENOP(Shr);
481       GENOP(Shrs);
482       GENOP(Rot);
483       default:
484         assert("binop: THIS SHOULD NOT HAPPEN");
485     }
486   }
487
488   return asm_node;
489 }
490
491
492
493 /**
494  * Transforms a Load.
495  *
496  * @param mod     the debug module
497  * @param block   the block the new node should belong to
498  * @param node    the ir Load node
499  * @param mode    node mode
500  * @return the created ia32 Load node
501  */
502 ir_node *gen_Load(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
503   return new_rd_ia32_Load(get_irn_dbg_info(node), current_ir_graph, block, get_Load_mem(node), get_Load_ptr(node), mode);
504 }
505
506
507
508 /**
509  * Transforms a Store.
510  *
511  * @param mod     the debug module
512  * @param block   the block the new node should belong to
513  * @param node    the ir Store node
514  * @param mode    node mode
515  * @return the created ia32 Store node
516  */
517 ir_node *gen_Store(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
518   return new_rd_ia32_Store(get_irn_dbg_info(node), current_ir_graph, block, get_Store_mem(node), get_Store_ptr(node), get_Store_value(node), mode);
519 }
520
521
522
523 /**
524  * Transforms the given firm node (and maybe some other related nodes)
525  * into one or more assembler nodes.
526  *
527  * @param node    the firm node
528  * @param env     the debug module
529  */
530 void transform_node(ir_node *node, void *env) {
531   firm_dbg_module_t *mod = (firm_dbg_module_t *)env;
532   opcode  code           = get_irn_opcode(node);
533   ir_node *asm_node      = NULL;
534   ir_node *block;
535   ir_mode *mode;
536
537   if (is_Block(node))
538     return;
539
540   block = get_nodes_block(node);
541   mode  = get_irn_mode(node);
542
543 #define BINOP_COM(a)   case iro_##a: asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 1); break
544 #define BINOP_NCOM(a)  case iro_##a: asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 0); break
545 #define UNOP(a)        case iro_##a: asm_node = gen_##a(mod, block, node, get_irn_n(node, 0), mode); break
546 #define GEN(a)         case iro_##a: asm_node = gen_##a(mod, block, node, mode); break
547 #define IGN(a)         case iro_##a: break
548
549   DBG((mod, LEVEL_1, "transforming node %s (%ld) ... ", get_irn_opname(node), get_irn_node_nr(node)));
550
551   switch (code) {
552     BINOP_COM(Add);
553     BINOP_COM(Mul);
554     BINOP_COM(And);
555     BINOP_COM(Or);
556     BINOP_COM(Eor);
557     BINOP_COM(Cmp);
558
559     BINOP_NCOM(Sub);
560     BINOP_NCOM(Mod);
561     BINOP_NCOM(Shl);
562     BINOP_NCOM(Shr);
563     BINOP_NCOM(Shrs);
564     BINOP_NCOM(Rot);
565 //    BINOP_ARITH_NCOM(DivMod);
566
567     UNOP(Conv);
568     GEN(Load);
569     GEN(Store);
570   }
571
572   if (asm_node) {
573     exchange(node, asm_node);
574     DBG((mod, LEVEL_1, "created node %u\n", get_irn_node_nr(asm_node)));
575   }
576   else {
577     DBG((mod, LEVEL_1, "ignored\n"));
578   }
579 }