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