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