Fixed register allocation for fp != sp
[libfirm] / ir / be / arm / arm_transform.c
1 /* The codegenrator (transform FIRM into arm FIRM */
2 /* $Id$ */
3
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
7
8 #include "irnode_t.h"
9 #include "irgraph_t.h"
10 #include "irmode_t.h"
11 #include "irgmod.h"
12 #include "iredges.h"
13 #include "irvrfy.h"
14 #include "ircons.h"
15 #include "irprintf.h"
16 #include "dbginfo.h"
17 #include "iropt_t.h"
18 #include "debug.h"
19
20 #include "../benode_t.h"
21 #include "bearch_arm_t.h"
22
23 #include "arm_nodes_attr.h"
24 #include "../arch/archop.h"     /* we need this for Min and Max nodes */
25 #include "arm_transform.h"
26 #include "arm_new_nodes.h"
27 #include "arm_map_regs.h"
28
29 #include "gen_arm_regalloc_if.h"
30
31 #include <limits.h>
32
33
34 extern ir_op *get_op_Mulh(void);
35
36
37
38 /****************************************************************************************************
39  *                  _        _                        __                           _   _
40  *                 | |      | |                      / _|                         | | (_)
41  *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
42  * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
43  * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
44  * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
45  *
46  ****************************************************************************************************/
47
48 /** Execute ROL. */
49 static unsigned do_rol(unsigned v, unsigned rol)
50 {
51         return (v << rol) | (v >> (32 - rol));
52 }
53
54 typedef struct vals_ {
55         int ops;
56         unsigned char values[4];
57         unsigned char shifts[4];
58 } vals;
59
60 static void gen_vals_from_word(unsigned int value, vals *result)
61 {
62         int initial = 0;
63
64         memset(result, 0, sizeof(*result));
65
66         /* special case: we prefer shift amount 0 */
67         if (value < 0x100) {
68                 result->values[0] = value;
69                 result->ops       = 1;
70                 return;
71         }
72
73         while (value != 0) {
74                 if (value & 0xFF) {
75                         unsigned v = do_rol(value, 8) & 0xFFFFFF;
76                         int shf = 0;
77                         for (;;) {
78                                 if ((v & 3) != 0)
79                                         break;
80                                 shf += 2;
81                                 v >>= 2;
82                         }
83                         v  &= 0xFF;
84                         shf = (initial + shf - 8) & 0x1F;
85                         result->values[result->ops] = v;
86                         result->shifts[result->ops] = shf;
87                         ++result->ops;
88
89                         value ^= do_rol(v, shf) >> initial;
90                 }
91                 else {
92                         value >>= 8;
93                         initial += 8;
94                 }
95         }
96 }
97
98 /**
99  * Creates a arm_Const node.
100  */
101 static ir_node *create_const_node(arm_transform_env_t *env, long value) {
102     tarval *tv = new_tarval_from_long(value, mode_Iu);
103         return new_rd_arm_Mov_i(env->dbg, env->irg, env->block, env->mode, tv);
104 }
105
106 /**
107  * Creates a arm_Const_Neg node.
108  */
109 static ir_node *create_const_neg_node(arm_transform_env_t *env, long value) {
110     tarval *tv = new_tarval_from_long(value, mode_Iu);
111         return new_rd_arm_Mvn_i(env->dbg, env->irg, env->block, env->mode, tv);
112 }
113
114 #define NEW_BINOP_NODE(opname, env, op1, op2) new_rd_arm_##opname(env->dbg, env->irg, env->block, op1, op2, env->mode)
115
116 /**
117  * Encodes an immediate with shifter operand
118  */
119 static unsigned int arm_encode_imm_w_shift(unsigned int shift, unsigned int immediate) {
120         return immediate | ((shift>>1)<<8);
121 }
122
123 /**
124  * Decode an immediate with shifter operand
125  */
126 unsigned int arm_decode_imm_w_shift(tarval *tv) {
127         unsigned l = get_tarval_long(tv);
128         unsigned rol = (l & ~0xFF) >> 7;
129
130         return do_rol(l & 0xFF, rol);
131 }
132
133 /**
134  * Creates a possible DAG for an constant.
135  */
136 static ir_node *create_const_graph_value(arm_transform_env_t *env, unsigned int value) {
137         ir_node *result;
138         int negate = 0;
139         vals v, vn;
140         int cnt;
141
142         gen_vals_from_word(value, &v);
143         gen_vals_from_word(~value, &vn);
144
145         if (vn.ops < v.ops) {
146                 /* remove bits */
147                 result = create_const_neg_node(env, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
148
149                 for (cnt = 1; cnt < vn.ops; ++cnt) {
150                         tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]), mode_Iu);
151                         ir_node *bic_i_node = new_rd_arm_Bic_i(env->dbg, env->irg, env->block, result, env->mode, tv);
152                         result = bic_i_node;
153                 }
154         }
155         else {
156                 /* add bits */
157                 result = create_const_node(env, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
158
159                 for (cnt = 1; cnt < v.ops; ++cnt) {
160                         tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]), mode_Iu);
161                         ir_node *orr_i_node = new_rd_arm_Or_i(env->dbg, env->irg, env->block, result, env->mode, tv);
162                         result = orr_i_node;
163                 }
164         }
165         return result;
166 }
167
168 static ir_node *create_const_graph(arm_transform_env_t *env) {
169         int value = get_tarval_long(get_Const_tarval(env->irn));
170         return create_const_graph_value(env, value);
171 }
172
173
174
175 static ir_node *gen_Const(arm_transform_env_t *env) {
176         ir_node *result;
177         assert(env->mode != mode_E && "IEEE Extended FP not supported");
178         if (env->mode == mode_F) {
179                 result = new_rd_arm_fConst(env->dbg, env->irg, env->block, env->mode);
180                 get_arm_attr(result)->value = get_Const_tarval(env->irn);
181         } else if (env->mode == mode_D) {
182                 result = new_rd_arm_fConst(env->dbg, env->irg, env->block, env->mode);
183                 get_arm_attr(result)->value = get_Const_tarval(env->irn);
184         } else if (env->mode == mode_P) {
185                 return env->irn;
186         } else {
187                 result = create_const_graph(env);
188         }
189         return result;
190 }
191
192 static ir_node *gen_mask(arm_transform_env_t *env, ir_node *op, int result_bits) {
193         unsigned mask_bits = (1 << result_bits) - 1;
194         ir_node *mask_node = create_const_graph_value(env, mask_bits);
195         return new_rd_arm_And(env->dbg, env->irg, env->block, op, mask_node, get_irn_mode(env->irn), ARM_SHF_NONE, NULL);
196 }
197
198 static ir_node *gen_sign_extension(arm_transform_env_t *env, ir_node *op, int result_bits) {
199         int shift_width = 32 - result_bits;
200         ir_node *shift_const_node = create_const_graph_value(env, shift_width);
201         ir_node *lshift_node = new_rd_arm_Shl(env->dbg, env->irg, env->block, op, shift_const_node, get_irn_mode(op));
202         ir_node *rshift_node = new_rd_arm_Shrs(env->dbg, env->irg, env->block, lshift_node, shift_const_node, get_irn_mode(env->irn));
203         return rshift_node;
204 }
205
206 /**
207  * Transforms a Conv node.
208  *
209  * @param env   The transformation environment
210  * @return the created arm Conv node
211  */
212 static ir_node *gen_Conv(arm_transform_env_t *env) {
213         ir_node *op      = get_Conv_op(env->irn);
214         ir_mode *in_mode = get_irn_mode(op);
215         ir_mode *out_mode = env->mode;
216
217         assert( in_mode != mode_E && "");
218         assert( in_mode != mode_Ls && "");
219         assert( in_mode != mode_Lu && "");
220         assert( out_mode != mode_E && "");
221         assert( out_mode != mode_Ls && "");
222         assert( out_mode != mode_Lu && "");
223
224         if (in_mode == out_mode)
225                 return op;
226
227         if ((mode_is_int(in_mode) || mode_is_reference(in_mode))
228                 && (mode_is_reference(out_mode) || mode_is_int(out_mode))) {
229                 int in_bits = get_mode_size_bits(in_mode);
230                 int out_bits = get_mode_size_bits(out_mode);
231                 int in_sign = get_mode_sign(in_mode);
232                 int out_sign = get_mode_sign(out_mode);
233
234                 // 32 -> 32
235                         // NOPpen
236                 if (in_bits == out_bits && in_bits == 32)
237                         return op;
238
239                 // 16 -> 16
240                         // unsigned -> unsigned
241                                 // NOP
242                         // unsigned -> signed
243                                 // sign extension (31:16)=(15)
244                         // signed -> unsigned
245                                 // maskieren (31:16)=0
246                         // signed -> signed
247                                 // NOP
248                 if (in_bits == out_bits && out_bits < 32) {
249                         if (in_sign && !out_sign) {
250                                 return gen_mask(env, op, out_bits);
251                         } else {
252                                 return gen_sign_extension(env, op, out_bits);
253                         }
254                 }
255
256                 // 16 -> 32
257                         // unsigned -> unsigned
258                                 // NOP
259                         // unsigned -> signed
260                                 // NOP
261                         // signed -> unsigned
262                                 // sign extension (31:16)=(15)
263                         // signed -> signed
264                                 // sign extension (31:16)=(15)
265                 if (in_bits < out_bits) {
266                         if (in_sign) {
267                                 return gen_sign_extension(env, op, out_bits);
268                         } else {
269                                 return op;
270                         }
271                 }
272
273                 // 32 -> 16
274                         // unsigned -> unsigned
275                                 // maskieren (31:16)=0
276                         // unsigned -> signed
277                                 // maskieren (31:16)=0
278                         // signed -> unsigned
279                                 // maskieren (31:16)=0
280                         // signed -> signed
281                                 // sign extension (erledigt auch maskieren) (31:16)=(15)
282                 if (in_bits > out_bits) {
283                         if (in_sign && out_sign) {
284                                 return gen_sign_extension(env, op, out_bits);
285                         } else {
286                                 return gen_mask(env, op, out_bits);
287                         }
288                 }
289                 assert(0 && "recheck integer conversion logic!");
290                 return env->irn;
291         } else if (in_mode == mode_D && out_mode == mode_F) {
292                 return new_rd_arm_fConvD2S(env->dbg, env->irg, env->block, op, env->mode);
293         } else if (in_mode == mode_F && out_mode == mode_D) {
294                 return new_rd_arm_fConvS2D(env->dbg, env->irg, env->block, op, env->mode);
295         } else if (mode_is_int(in_mode) && mode_is_float(out_mode)) {
296                 env->cg->have_fp = 1;
297                 return env->irn; /* TODO: implement int->float conversion*/
298         } else if (mode_is_float(in_mode) && mode_is_int(out_mode)) {
299                 env->cg->have_fp = 1;
300                 return env->irn; /* TODO: implement float->int conversion*/
301         } else {
302                 assert(0 && "not implemented conversion");
303                 return env->irn;
304         }
305 }
306
307 /**
308  * Return true if an operand is a shifter operand
309  */
310 static int is_shifter_operand(ir_node *n, arm_shift_modifier *pmod) {
311         arm_shift_modifier mod = ARM_SHF_NONE;
312
313         if (is_arm_Mov(n))
314                 mod = get_arm_shift_modifier(n);
315
316         *pmod = mod;
317         if (mod != ARM_SHF_NONE) {
318                 long v = get_tarval_long(get_arm_value(n));
319                 if (v < 32)
320                         return (int)v;
321         }
322         return 0;
323 }
324
325 /**
326  * Creates an arm Add.
327  *
328  * @param env   The transformation environment
329  * @return the created arm Add node
330  */
331 static ir_node *gen_Add(arm_transform_env_t *env) {
332         ir_node *irn = env->irn;
333         ir_node *op1 = get_Add_left(irn);
334         ir_node *op2 = get_Add_right(irn);
335         ir_node *op3;
336         int v;
337         arm_shift_modifier mod;
338
339         assert(env->mode != mode_E && "IEEE Extended FP not supported");
340
341         if (mode_is_float(env->mode)) {
342                 env->cg->have_fp = 1;
343                 return new_rd_arm_fAdd(env->dbg, env->irg, env->block, op1, op2, env->mode);
344         }
345         if (mode_is_numP(env->mode)) {
346                 if (is_arm_Mov_i(op1))
347                         return new_rd_arm_Add_i(env->dbg, env->irg, env->block, op2, env->mode,
348                                                 get_arm_value(op1));
349                 if (is_arm_Mov_i(op2))
350                         return new_rd_arm_Add_i(env->dbg, env->irg, env->block, op1, env->mode,
351                                                 get_arm_value(op2));
352
353                 /* check for MLA */
354                 if (is_arm_Mul(op1) && get_irn_n_edges(op1) == 1) {
355                         op3 = op2;
356                         op2 = get_irn_n(op1, 1);
357                         op1 = get_irn_n(op1, 0);
358
359                         return new_rd_arm_Mla(env->dbg, env->irg, env->block, op1, op2, op3, env->mode);
360                 }
361                 if (is_arm_Mul(op2) && get_irn_n_edges(op2) == 1) {
362                         op3 = op1;
363                         op1 = get_irn_n(op2, 0);
364                         op2 = get_irn_n(op2, 1);
365
366                         return new_rd_arm_Mla(env->dbg, env->irg, env->block, op1, op2, op3, env->mode);
367                 }
368
369                 /* is the first a shifter */
370                 v = is_shifter_operand(op1, &mod);
371                 if (v) {
372                         op1 = get_irn_n(op1, 0);
373                         return new_rd_arm_Add(env->dbg, env->irg, env->block, op2, op1, env->mode,
374                                               mod, new_tarval_from_long(v, mode_Iu));
375                 }
376                 /* is the second a shifter */
377                 v = is_shifter_operand(op2, &mod);
378                 if (v) {
379                         op2 = get_irn_n(op2, 0);
380                         return new_rd_arm_Add(env->dbg, env->irg, env->block, op1, op2, env->mode,
381                                               mod, new_tarval_from_long(v, mode_Iu));
382                 }
383
384                 /* normal ADD */
385                 return new_rd_arm_Add(env->dbg, env->irg, env->block, op1, op2, env->mode, ARM_SHF_NONE, NULL);
386         }
387
388         assert(0 && "unknown mode for add");
389         return NULL;
390 }
391
392 /**
393  * Creates an arm Mul.
394  *
395  * @param env   The transformation environment
396  * @return the created arm Mul node
397  */
398 static ir_node *gen_Mul(arm_transform_env_t *env) {
399         ir_node *irn = env->irn;
400         ir_node *op1 = get_Mul_left(irn);
401         ir_node *op2 = get_Mul_right(irn);
402
403         assert(env->mode != mode_E && "IEEE Extended FP not supported");
404
405         if (mode_is_float(env->mode)) {
406                 env->cg->have_fp = 1;
407                 return new_rd_arm_fMul(env->dbg, env->irg, env->block, op1, op2, env->mode);
408         }
409         return new_rd_arm_Mul(env->dbg, env->irg, env->block, op1, op2, env->mode);
410 }
411
412 /**
413  * Creates an arm floating point Div.
414  *
415  * @param env   The transformation environment
416  * @return the created arm fDiv node
417  */
418 static ir_node *gen_Quot(arm_transform_env_t *env) {
419         ir_node *irn = env->irn;
420         ir_node *op1 = get_Quot_left(irn);
421         ir_node *op2 = get_Quot_right(irn);
422
423         assert(mode_is_float(get_irn_mode(op1)));
424         assert(get_irn_mode(op1) != mode_E && "IEEE Extended FP not supported");
425
426         return new_rd_arm_fDiv(env->dbg, env->irg, env->block, op1, op2, env->mode);
427 }
428
429 #define GEN_INT_OP(op) \
430 static ir_node *gen_ ## op(arm_transform_env_t *env) { \
431         ir_node *irn = env->irn; \
432         ir_node *op1 = get_ ## op ## _left(irn); \
433         ir_node *op2 = get_ ## op ## _right(irn); \
434         int v; \
435         arm_shift_modifier mod; \
436  \
437         if (is_arm_Mov_i(op1)) \
438                 return new_rd_arm_ ## op ## _i(env->dbg, env->irg, env->block, op2, env->mode, \
439                                         get_arm_value(op1)); \
440         if (is_arm_Mov_i(op2)) \
441                 return new_rd_arm_ ## op ## _i(env->dbg, env->irg, env->block, op1, env->mode, \
442                                         get_arm_value(op2)); \
443         /* is the first a shifter */ \
444         v = is_shifter_operand(op1, &mod); \
445         if (v) { \
446                 op1 = get_irn_n(op1, 0); \
447                 return new_rd_arm_ ## op(env->dbg, env->irg, env->block, op2, op1, env->mode, \
448                                             mod, new_tarval_from_long(v, mode_Iu)); \
449         } \
450         /* is the second a shifter */ \
451         v = is_shifter_operand(op2, &mod); \
452         if (v) { \
453                 op2 = get_irn_n(op2, 0); \
454                 return new_rd_arm_ ## op(env->dbg, env->irg, env->block, op1, op2, env->mode, \
455                                             mod, new_tarval_from_long(v, mode_Iu)); \
456         } \
457         /* Normal op */ \
458         return new_rd_arm_ ## op(env->dbg, env->irg, env->block, op1, op2, env->mode, ARM_SHF_NONE, NULL); \
459 }
460
461
462 /**
463  * Creates an arm And.
464  *
465  * @param env   The transformation environment
466  * @return the created arm And node
467  */
468 static ir_node *gen_And(arm_transform_env_t *env);
469 GEN_INT_OP(And)
470
471 /**
472  * Creates an arm Orr.
473  *
474  * @param env   The transformation environment
475  * @return the created arm Or node
476  */
477 static ir_node *gen_Or(arm_transform_env_t *env);
478 GEN_INT_OP(Or)
479
480 /**
481  * Creates an arm Eor.
482  *
483  * @param env   The transformation environment
484  * @return the created arm Eor node
485  */
486 static ir_node *gen_Eor(arm_transform_env_t *env);
487 GEN_INT_OP(Eor)
488
489 /**
490  * Creates an arm Sub.
491  *
492  * @param env   The transformation environment
493  * @return the created arm Sub node
494  */
495 static ir_node *gen_Sub(arm_transform_env_t *env) {
496         ir_node *irn = env->irn;
497         ir_node *op1 = get_Sub_left(irn);
498         ir_node *op2 = get_Sub_right(irn);
499         int v;
500         arm_shift_modifier mod;
501
502         assert(env->mode != mode_E && "IEEE Extended FP not supported");
503
504         if (mode_is_float(env->mode)) {
505                 env->cg->have_fp = 1;
506                 return new_rd_arm_fSub(env->dbg, env->irg, env->block, op1, op2, env->mode);
507         }
508         if (mode_is_numP(env->mode)) {
509                 if (is_arm_Mov_i(op1))
510                         return new_rd_arm_Rsb_i(env->dbg, env->irg, env->block, op2, env->mode,
511                                                 get_arm_value(op1));
512                 if (is_arm_Mov_i(op2))
513                         return new_rd_arm_Sub_i(env->dbg, env->irg, env->block, op1, env->mode,
514                                                 get_arm_value(op2));
515
516                 /* is the first a shifter */
517                 v = is_shifter_operand(op1, &mod);
518                 if (v) {
519                         op1 = get_irn_n(op1, 0);
520                         return new_rd_arm_Rsb(env->dbg, env->irg, env->block, op2, op1, env->mode,
521                                               mod, new_tarval_from_long(v, mode_Iu));
522                 }
523                 /* is the second a shifter */
524                 v = is_shifter_operand(op2, &mod);
525                 if (v) {
526                         op2 = get_irn_n(op2, 0);
527                         return new_rd_arm_Sub(env->dbg, env->irg, env->block, op1, op2, env->mode,
528                                               mod, new_tarval_from_long(v, mode_Iu));
529                 }
530                 /* normal sub */
531                 return new_rd_arm_Sub(env->dbg, env->irg, env->block, op1, op2, env->mode, ARM_SHF_NONE, NULL);
532         }
533         assert(0 && "unknown mode for sub");
534         return NULL;
535 }
536
537 /**
538  * Creates an arm Shl.
539  *
540  * @param env   The transformation environment
541  * @return the created arm Shl node
542  */
543 static ir_node *gen_Shl(arm_transform_env_t *env) {
544         ir_node *result;
545         ir_node *irn = env->irn;
546         ir_node *op1 = get_Shl_left(irn);
547         ir_node *op2 = get_Shl_right(irn);
548
549         if (is_arm_Mov_i(op2)) {
550                 result = new_rd_arm_Mov(env->dbg, env->irg, env->block, op1, env->mode,
551                                         ARM_SHF_LSL, get_arm_value(op2));
552         } else {
553                 result = new_rd_arm_Shl(env->dbg, env->irg, env->block, op1, op2, env->mode);
554         }
555         return result;
556 }
557
558 /**
559  * Creates an arm Shr.
560  *
561  * @param env   The transformation environment
562  * @return the created arm Shr node
563  */
564 static ir_node *gen_Shr(arm_transform_env_t *env) {
565         ir_node *result;
566         ir_node *irn = env->irn;
567         ir_node *op1 = get_Shr_left(irn);
568         ir_node *op2 = get_Shr_right(irn);
569
570         if (is_arm_Mov_i(op2)) {
571                 result = new_rd_arm_Mov(env->dbg, env->irg, env->block, op1, env->mode,
572                                         ARM_SHF_LSR, get_arm_value(op2));
573         } else {
574                 result = new_rd_arm_Shr(env->dbg, env->irg, env->block, op1, op2, env->mode);
575         }
576         return result;
577 }
578
579 /**
580  * Creates an arm Shrs.
581  *
582  * @param env   The transformation environment
583  * @return the created arm Shrs node
584  */
585 static ir_node *gen_Shrs(arm_transform_env_t *env) {
586         ir_node *result;
587         ir_node *irn = env->irn;
588         ir_node *op1 = get_Shrs_left(irn);
589         ir_node *op2 = get_Shrs_right(irn);
590
591         if (is_arm_Mov_i(op2)) {
592                 result = new_rd_arm_Mov(env->dbg, env->irg, env->block, op1, env->mode,
593                                         ARM_SHF_ASR, get_arm_value(op2));
594         } else {
595                 result = new_rd_arm_Shrs(env->dbg, env->irg, env->block, op1, op2, env->mode);
596         }
597         return result;
598 }
599
600 /**
601  * Transforms a Not node.
602  *
603  * @param env   The transformation environment
604  * @return the created arm Not node
605  */
606 static ir_node *gen_Not(arm_transform_env_t *env) {
607         ir_node *op = get_Not_op(env->irn);
608         int v;
609         arm_shift_modifier mod = ARM_SHF_NONE;
610         tarval  *tv = NULL;
611
612         v = is_shifter_operand(op, &mod);
613         if (v) {
614                 op = get_irn_n(op, 0);
615                 tv = new_tarval_from_long(v, mode_Iu);
616         }
617         return new_rd_arm_Mvn(env->dbg, env->irg, env->block, op, env->mode, mod, tv);
618 }
619
620 /**
621  * Transforms an Abs node.
622  *
623  * @param env   The transformation environment
624  * @return the created arm Abs node
625  */
626 static ir_node *gen_Abs(arm_transform_env_t *env) {
627         ir_node *op = get_Abs_op(env->irn);
628
629         assert(env->mode != mode_E && "IEEE Extended FP not supported");
630
631         if (mode_is_float(env->mode)) {
632                 env->cg->have_fp = 1;
633                 return new_rd_arm_fAbs(env->dbg, env->irg, env->block, op, env->mode);
634         }
635
636         return new_rd_arm_Abs(env->dbg, env->irg, env->block, op, env->mode);
637 }
638
639 /**
640  * Transforms a Minus node.
641  *
642  * @param env   The transformation environment
643  * @return the created arm Minus node
644  */
645 static ir_node *gen_Minus(arm_transform_env_t *env) {
646         ir_node *op = get_Minus_op(env->irn);
647
648         if (mode_is_float(env->mode)) {
649                 return new_rd_arm_fMinus(env->dbg, env->irg, env->block, op, env->mode);
650         }
651         return new_rd_arm_Rsb_i(env->dbg, env->irg, env->block, op, env->mode, get_mode_null(env->mode));
652 }
653
654 /**
655  * Transforms a Load.
656  *
657  * @param mod     the debug module
658  * @param block   the block the new node should belong to
659  * @param node    the ir Load node
660  * @param mode    node mode
661  * @return the created arm Load node
662  */
663 static ir_node *gen_Load(arm_transform_env_t *env) {
664         ir_node *node = env->irn;
665         ir_mode *mode = get_Load_mode(node);
666
667         if (mode_is_float(mode)) {
668                 env->cg->have_fp = 1;
669                 /* FIXME: set the load mode */
670                 return new_rd_arm_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
671         }
672         if (mode == mode_Bu) {
673                 return new_rd_arm_Loadb(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
674         }
675         if (mode == mode_Bs) {
676                 return new_rd_arm_Loadbs(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
677         }
678         if (mode == mode_Hu) {
679                 return new_rd_arm_Loadh(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
680         }
681         if (mode == mode_Hs) {
682                 return new_rd_arm_Loadhs(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
683         }
684         if (mode_is_reference(mode)) {
685                 return new_rd_arm_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
686         }
687         return new_rd_arm_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
688 }
689
690 /**
691  * Transforms a Store.
692  *
693  * @param mod     the debug module
694  * @param block   the block the new node should belong to
695  * @param node    the ir Store node
696  * @param mode    node mode
697  * @return the created arm Store node
698  */
699 static ir_node *gen_Store(arm_transform_env_t *env) {
700         ir_node *node = env->irn;
701         ir_mode *mode = get_irn_mode(get_Store_value(node));
702         assert(env->mode != mode_E && "IEEE Extended FP not supported");
703
704         if (mode_is_float(mode)) {
705                 env->cg->have_fp = 1;
706                 /* FIXME: set the store mode */
707                 return new_rd_arm_fStore(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
708         }
709         if (mode == mode_Bu) {
710                 return new_rd_arm_Storeb(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
711         }
712         if (mode == mode_Bs) {
713                 return new_rd_arm_Storebs(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
714         }
715         if (mode == mode_Hu) {
716                 return new_rd_arm_Storeh(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
717         }
718         if (mode == mode_Hs) {
719                 return new_rd_arm_Storehs(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
720         }
721         return new_rd_arm_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
722 }
723
724
725 static ir_node *gen_Cond(arm_transform_env_t *env) {
726         ir_node *result   = NULL;
727         ir_node *selector = get_Cond_selector(env->irn);
728         ir_node *irn      = env->irn;
729
730         if ( get_irn_mode(selector) == mode_b ) {
731                 //CondJmp
732                 ir_node *proj_node = get_Cond_selector(irn);
733                 ir_node *cmp_node = get_Proj_pred(proj_node);
734                 ir_node *op1 = get_Cmp_left(cmp_node);
735                 ir_node *op2 = get_Cmp_right(cmp_node);
736                 result = new_rd_arm_CondJmp(env->dbg, env->irg, env->block, op1, op2, mode_T);
737                 set_arm_proj_num(result, get_Proj_proj(proj_node));
738         } else {
739                 //SwitchJmp
740                 ir_node *op = get_irn_n(env->irn, 0);
741                 ir_node *const_graph;
742                 ir_node *sub;
743                 ir_node *const_node;
744
745                 ir_node *proj;
746                 const ir_edge_t *edge;
747                 int min = INT_MAX;
748                 int max = INT_MIN;
749                 int translation;
750                 int norm_max;
751                 int norm_min;
752                 int pn;
753                 arm_transform_env_t const_env;
754                 int n_projs;
755                 ir_node **projs;
756
757                 foreach_out_edge(irn, edge) {
758                         proj = get_edge_src_irn(edge);
759                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
760
761                         pn = get_Proj_proj(proj);
762
763                         min = pn<min ? pn : min;
764                         max = pn>max ? pn : max;
765                 }
766                 translation = min;
767                 norm_max = max - translation;
768                 norm_min = min - translation;
769
770                 n_projs = norm_max + 1;
771                 projs = xcalloc(n_projs , sizeof(ir_node*));
772
773
774                 foreach_out_edge(irn, edge) {
775                         proj = get_edge_src_irn(edge);
776                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
777
778                         pn = get_Proj_proj(proj) - translation;
779                         set_Proj_proj(proj, pn);
780                 }
781
782
783                 const_node = new_rd_Const(env->dbg, env->irg, env->block, mode_Iu, new_tarval_from_long(translation, mode_Iu));
784                 const_env = *env;
785                 const_env.mode = mode_Is;
786                 const_env.irn = const_node;
787                 const_graph = gen_Const(&const_env);
788                 sub = new_rd_arm_Sub(env->dbg, env->irg, env->block, op, const_graph, get_irn_mode(op), ARM_SHF_NONE, NULL);
789                 result = new_rd_arm_SwitchJmp(env->dbg, env->irg, env->block, sub, mode_T);
790                 set_arm_n_projs(result, n_projs);
791                 set_arm_default_proj_num(result, get_Cond_defaultProj(irn)-translation);
792         }
793         return result;
794 }
795
796 /**
797  * Returns the name of a SymConst.
798  * @param symc  the SymConst
799  * @return name of the SymConst
800  */
801 const char *get_sc_name(ir_node *symc) {
802         if (get_irn_opcode(symc) != iro_SymConst)
803                 return "NONE";
804
805         switch (get_SymConst_kind(symc)) {
806                 case symconst_addr_name:
807                         return get_id_str(get_SymConst_name(symc));
808
809                 case symconst_addr_ent:
810                         return get_entity_ld_name(get_SymConst_entity(symc));
811
812                 default:
813                         assert(0 && "Unsupported SymConst");
814         }
815
816         return NULL;
817 }
818
819 static ir_node *gen_SymConst(arm_transform_env_t *env) {
820         return new_rd_arm_SymConst(env->dbg, env->irg, env->block,
821                                    env->mode, get_sc_name(env->irn));
822 }
823
824
825
826 /**
827  * Transforms a CopyB node.
828  *
829  * @param env   The transformation environment
830  * @return The transformed node.
831  */
832 static ir_node *gen_CopyB(arm_transform_env_t *env) {
833         ir_node  *res   = NULL;
834         dbg_info *dbg   = env->dbg;
835         ir_graph *irg   = env->irg;
836         ir_mode  *mode  = env->mode;
837         ir_node  *block = env->block;
838         ir_node  *node  = env->irn;
839         ir_node  *src   = get_CopyB_src(node);
840         ir_node  *dst   = get_CopyB_dst(node);
841         ir_node  *mem   = get_CopyB_mem(node);
842         int       size  = get_type_size_bytes(get_CopyB_type(node));
843         ir_node *src_copy;
844         ir_node *dst_copy;
845
846         arm_transform_env_t const_env;
847         const_env.block    = block;
848         const_env.dbg      = dbg;
849         const_env.irg      = irg;
850         const_env.irn      = node;
851         DEBUG_ONLY(const_env.mod      = env->mod;)
852         const_env.mode     = mode_Iu;
853
854         src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, src);
855         dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, dst);
856
857         res = new_rd_arm_CopyB( dbg, irg, block, dst_copy, src_copy, new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), mem, mode);
858         set_arm_value(res, new_tarval_from_long(size, mode_Iu));
859
860         return res;
861 }
862
863
864
865
866
867 /********************************************
868  *  _                          _
869  * | |                        | |
870  * | |__   ___ _ __   ___   __| | ___  ___
871  * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
872  * | |_) |  __/ | | | (_) | (_| |  __/\__ \
873  * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
874  *
875  ********************************************/
876
877 /**
878  * Return an expanding stack offset.
879  * Note that function is called in the transform phase
880  * where the stack offsets are still relative regarding
881  * the first (frame allocating) IncSP.
882  * However this is exactly what we want because frame
883  * access must be done relative the the fist IncSP ...
884  */
885 static int get_sp_expand_offset(ir_node *inc_sp) {
886         unsigned offset    = be_get_IncSP_offset(inc_sp);
887         be_stack_dir_t dir = be_get_IncSP_direction(inc_sp);
888
889         if (offset == BE_STACK_FRAME_SIZE)
890                 return 0;
891         return dir == be_stack_dir_expand ? (int)offset : -(int)offset;
892 }
893
894 static ir_node *gen_StackParam(arm_transform_env_t *env) {
895 #if 0
896         ir_node *new_op = NULL;
897         ir_node *node   = env->irn;
898         ir_node *noreg  = ia32_new_NoReg_gp(env->cg);
899         ir_node *mem    = new_rd_NoMem(env->irg);
900         ir_node *ptr    = get_irn_n(node, 0);
901         entity  *ent    = be_get_frame_entity(node);
902         ir_mode *mode   = env->mode;
903
904 //      /* If the StackParam has only one user ->     */
905 //      /* put it in the Block where the user resides */
906 //      if (get_irn_n_edges(node) == 1) {
907 //              env->block = get_nodes_block(get_edge_src_irn(get_irn_out_edge_first(node)));
908 //      }
909
910         if (mode_is_float(mode)) {
911                 if (USE_SSE2(env->cg))
912                         new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
913                 else {
914                         env->cg->used_x87 = 1;
915                         new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
916                 }
917         }
918         else {
919                 new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
920         }
921
922         set_ia32_frame_ent(new_op, ent);
923         set_ia32_use_frame(new_op);
924
925         set_ia32_am_support(new_op, ia32_am_Source);
926         set_ia32_op_type(new_op, ia32_AddrModeS);
927         set_ia32_am_flavour(new_op, ia32_B);
928         set_ia32_ls_mode(new_op, mode);
929
930         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
931
932         return new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode, 0);
933 #endif
934 }
935
936 /**
937  * Transforms a FrameAddr into an ia32 Add.
938  */
939 static ir_node *gen_be_FrameAddr(arm_transform_env_t *env) {
940         ir_node *node   = env->irn;
941         entity  *ent    = be_get_frame_entity(node);
942         int     offset  = get_entity_offset_bytes(ent);
943         ir_node *op     = get_irn_n(node, 0);
944         ir_node *cnst;
945
946         if (be_is_IncSP(op)) {
947                 /* BEWARE: we get an offset which is absolute from an offset that
948                    is relative. Both must be merged */
949                 offset += get_sp_expand_offset(op);
950         }
951         cnst = create_const_graph_value(env, (unsigned)offset);
952         if (is_arm_Mov_i(cnst)) {
953                 return new_rd_arm_Add_i(env->dbg, env->irg, env->block, op, env->mode,
954                                         get_arm_value(cnst));
955         }
956         return new_rd_arm_Add(env->dbg, env->irg, env->block, op, cnst, env->mode, ARM_SHF_NONE, NULL);
957 }
958
959 /**
960  * Transforms a FrameLoad into an ia32 Load.
961  */
962 static ir_node *gen_FrameLoad(arm_transform_env_t *env) {
963 #if 0
964         ir_node *new_op = NULL;
965         ir_node *node   = env->irn;
966         ir_node *noreg  = ia32_new_NoReg_gp(env->cg);
967         ir_node *mem    = get_irn_n(node, 0);
968         ir_node *ptr    = get_irn_n(node, 1);
969         entity  *ent    = be_get_frame_entity(node);
970         ir_mode *mode   = get_type_mode(get_entity_type(ent));
971
972         if (mode_is_float(mode)) {
973                 if (USE_SSE2(env->cg))
974                         new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
975                 else {
976                         env->cg->used_x87 = 1;
977                         new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
978                 }
979         }
980         else {
981                 new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
982         }
983
984         set_ia32_frame_ent(new_op, ent);
985         set_ia32_use_frame(new_op);
986
987         set_ia32_am_support(new_op, ia32_am_Source);
988         set_ia32_op_type(new_op, ia32_AddrModeS);
989         set_ia32_am_flavour(new_op, ia32_B);
990         set_ia32_ls_mode(new_op, mode);
991
992         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
993
994         return new_op;
995 #endif
996 }
997
998
999 /**
1000  * Transforms a FrameStore into an ia32 Store.
1001  */
1002 static ir_node *gen_FrameStore(arm_transform_env_t *env) {
1003 #if 0
1004         ir_node *new_op = NULL;
1005         ir_node *node   = env->irn;
1006         ir_node *noreg  = ia32_new_NoReg_gp(env->cg);
1007         ir_node *mem    = get_irn_n(node, 0);
1008         ir_node *ptr    = get_irn_n(node, 1);
1009         ir_node *val    = get_irn_n(node, 2);
1010         entity  *ent    = be_get_frame_entity(node);
1011         ir_mode *mode   = get_irn_mode(val);
1012
1013         if (mode_is_float(mode)) {
1014                 if (USE_SSE2(env->cg))
1015                         new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1016                 else {
1017                         env->cg->used_x87 = 1;
1018                         new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1019                 }
1020         }
1021         else if (get_mode_size_bits(mode) == 8) {
1022                 new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1023         }
1024         else {
1025                 new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1026         }
1027
1028         set_ia32_frame_ent(new_op, ent);
1029         set_ia32_use_frame(new_op);
1030
1031         set_ia32_am_support(new_op, ia32_am_Dest);
1032         set_ia32_op_type(new_op, ia32_AddrModeD);
1033         set_ia32_am_flavour(new_op, ia32_B);
1034         set_ia32_ls_mode(new_op, mode);
1035
1036         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1037
1038         return new_op;
1039 #endif
1040 }
1041
1042
1043 // static ir_node *gen_be_Copy(arm_transform_env_t *env, ir_node *op) {
1044 //      return new_rd_arm_Copy(env->dbg, env->irg, env->block, op, env->mode);
1045 // }
1046
1047 /*********************************************************
1048  *                  _             _      _
1049  *                 (_)           | |    (_)
1050  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
1051  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
1052  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
1053  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
1054  *
1055  *********************************************************/
1056
1057 /************************************************************************/
1058 /* move constants out of startblock                                       */
1059 /************************************************************************/
1060 void arm_move_consts(ir_node *node, void *env) {
1061         arm_code_gen_t *cgenv = (arm_code_gen_t *)env;
1062         arm_transform_env_t tenv;
1063         int i;
1064
1065         if (is_Block(node))
1066                 return;
1067
1068         tenv.irg = current_ir_graph;
1069         DEBUG_ONLY(tenv.mod = cgenv->mod);
1070
1071         if (is_Phi(node)) {
1072                 for (i = 0; i < get_irn_arity(node); i++) {
1073                         ir_node *pred = get_irn_n(node,i);
1074                         opcode pred_code = get_irn_opcode(pred);
1075                         if (pred_code == iro_Const) {
1076                                 ir_node *const_graph;
1077                                 tenv.block    = get_nodes_block(get_irn_n(get_nodes_block(node),i));
1078                                 tenv.dbg      = get_irn_dbg_info(pred);
1079                                 tenv.irn      = pred;
1080                                 tenv.mode     = get_irn_mode(pred);
1081                                 const_graph = create_const_graph(&tenv);
1082                                 set_irn_n(node, i, const_graph);
1083                         } else if (pred_code == iro_SymConst) {
1084                                 const char *str = get_sc_name(pred);
1085                                 ir_node *symconst_node;
1086                                 symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1087                                         current_ir_graph, get_nodes_block(get_irn_n(get_nodes_block(node),i)),
1088                                         get_irn_mode(pred), str);
1089                                 set_irn_n(node, i, symconst_node);
1090                         }
1091                 }
1092                 return;
1093         }
1094         for (i = 0; i < get_irn_arity(node); i++) {
1095                 ir_node *pred = get_irn_n(node,i);
1096                 opcode pred_code = get_irn_opcode(pred);
1097                 if (pred_code == iro_Const) {
1098                         ir_node *const_graph;
1099                         tenv.block  = get_nodes_block(node);
1100                         tenv.dbg    = get_irn_dbg_info(pred);
1101                         tenv.irn    = pred;
1102                         tenv.mode   = get_irn_mode(pred);
1103                         const_graph = create_const_graph(&tenv);
1104                         set_irn_n(node, i, const_graph);
1105                 } else if (pred_code == iro_SymConst) {
1106                         const char *str = get_sc_name(pred);
1107                         ir_node *symconst_node;
1108                         symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1109                                 current_ir_graph, get_nodes_block(node),
1110                                 get_irn_mode(pred), str);
1111                         set_irn_n(node, i, symconst_node);
1112                 }
1113         }
1114 }
1115
1116
1117 /************************************************************************/
1118 /* move symbolic constants out of startblock                            */
1119 /************************************************************************/
1120 void arm_move_symconsts(ir_node *node, void *env) {
1121         int i;
1122
1123         if (is_Block(node))
1124                 return;
1125
1126         for (i = 0; i < get_irn_arity(node); i++) {
1127                 ir_node *pred      = get_irn_n(node,i);
1128                 opcode   pred_code = get_irn_opcode(pred);
1129
1130                 if (pred_code == iro_SymConst) {
1131                         const char *str = get_sc_name(pred);
1132                         ir_node    *symconst_node;
1133
1134                         symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1135                                 current_ir_graph, get_nodes_block(node), get_irn_mode(pred), str);
1136                         set_irn_n(node, i, symconst_node);
1137                 }
1138         }
1139 }
1140
1141 /**
1142  * the BAD transformer.
1143  */
1144 static ir_node *bad_transform(arm_transform_env_t *env) {
1145         ir_fprintf(stderr, "Not implemented: %+F\n", env->irn);
1146         assert(0);
1147         return NULL;
1148 }
1149
1150 /**
1151  * Enters all transform functions into the generic pointer
1152  */
1153 void arm_register_transformers(void) {
1154         ir_op *op_Max, *op_Min, *op_Mulh;
1155
1156         /* first clear the generic function pointer for all ops */
1157         clear_irp_opcodes_generic_func();
1158
1159 #define FIRM_OP(a)     op_##a->ops.generic = (op_func)gen_##a
1160 #define BAD(a)         op_##a->ops.generic = (op_func)bad_transform
1161 #define IGN(a)
1162
1163         FIRM_OP(Add);  // done
1164         FIRM_OP(Mul);  // done
1165         FIRM_OP(Quot); // done
1166         FIRM_OP(And);  // done
1167         FIRM_OP(Or);   // done
1168         FIRM_OP(Eor);  // done
1169
1170         FIRM_OP(Sub);  // done
1171         FIRM_OP(Shl);  // done
1172         FIRM_OP(Shr);  // done
1173         FIRM_OP(Shrs); // done
1174
1175         FIRM_OP(Minus); // done
1176         FIRM_OP(Not);   // done
1177         FIRM_OP(Abs);   // done
1178
1179         FIRM_OP(CopyB); // done
1180         FIRM_OP(Const); // TODO: floating point consts
1181         FIRM_OP(Conv); // TODO: floating point conversions
1182
1183         FIRM_OP(Load);   // done
1184         FIRM_OP(Store);  // done
1185
1186         FIRM_OP(SymConst);
1187         FIRM_OP(Cond);    // integer done
1188
1189         /* TODO: implement these nodes */
1190
1191         IGN(Div);    // intrinsic lowering
1192         IGN(Mod);    // intrinsic lowering
1193         IGN(DivMod); // TODO: implement DivMod
1194
1195         IGN(Mux);
1196         IGN(Unknown);
1197         IGN(Cmp);     // done, implemented in cond
1198
1199         /* You probably don't need to handle the following nodes */
1200
1201         IGN(Call);
1202         IGN(Proj);
1203         IGN(Alloc);
1204
1205         IGN(Block);
1206         IGN(Start);
1207         IGN(End);
1208         IGN(NoMem);
1209         IGN(Phi);
1210         IGN(IJmp);
1211         IGN(Jmp);     // emitter done
1212         IGN(Break);
1213         IGN(Sync);
1214
1215         BAD(Raise);
1216         BAD(Sel);
1217         BAD(InstOf);
1218         BAD(Cast);
1219         BAD(Free);
1220         BAD(Tuple);
1221         BAD(Id);
1222         BAD(Bad);
1223         BAD(Confirm);
1224         BAD(Filter);
1225         BAD(CallBegin);
1226         BAD(EndReg);
1227         BAD(EndExcept);
1228
1229         FIRM_OP(be_FrameAddr);
1230
1231         op_Max = get_op_Max();
1232         if (op_Max)
1233                 BAD(Max);
1234         op_Min = get_op_Min();
1235         if (op_Min)
1236                 BAD(Min);
1237         op_Mulh = get_op_Mulh();
1238         if (op_Mulh)
1239                 BAD(Mulh);
1240
1241 #undef IGN
1242 #undef FIRM_OP
1243 #undef BAD
1244 }
1245
1246 typedef ir_node *(transform_func)(arm_transform_env_t *env);
1247
1248 /**
1249  * Transforms the given firm node (and maybe some other related nodes)
1250  * into one or more assembler nodes.
1251  *
1252  * @param node    the firm node
1253  * @param env     the debug module
1254  */
1255 void arm_transform_node(ir_node *node, void *env) {
1256         arm_code_gen_t *cg = (arm_code_gen_t *)env;
1257         ir_op *op          = get_irn_op(node);
1258         ir_node *asm_node  = NULL;
1259
1260         if (op == op_Block)
1261                 return;
1262
1263         DBG((cg->mod, LEVEL_1, "check %+F ... ", node));
1264
1265         if (op->ops.generic) {
1266                 arm_transform_env_t tenv;
1267                 transform_func *transform = (transform_func *)op->ops.generic;
1268
1269                 tenv.cg       = cg;
1270                 tenv.block    = get_nodes_block(node);
1271                 tenv.dbg      = get_irn_dbg_info(node);
1272                 tenv.irg      = current_ir_graph;
1273                 tenv.irn      = node;
1274                 tenv.mode     = get_irn_mode(node);
1275                 DEBUG_ONLY(tenv.mod = cg->mod);
1276
1277                 asm_node = (*transform)(&tenv);
1278         }
1279
1280         if (asm_node) {
1281                 exchange(node, asm_node);
1282                 DB((cg->mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1283         }
1284         else {
1285                 DB((cg->mod, LEVEL_1, "ignored\n"));
1286         }
1287 }