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