88827ba8294611d97f538f142335b7e5240c604f
[libfirm] / ir / be / arm / arm_transform.c
1 /*
2  * Copyright (C) 1995-2008 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 #include "config.h"
27
28 #include "irnode_t.h"
29 #include "irgraph_t.h"
30 #include "irmode_t.h"
31 #include "irgmod.h"
32 #include "iredges.h"
33 #include "irvrfy.h"
34 #include "ircons.h"
35 #include "irprintf.h"
36 #include "dbginfo.h"
37 #include "iropt_t.h"
38 #include "debug.h"
39 #include "error.h"
40
41 #include "../benode.h"
42 #include "../beirg.h"
43 #include "../beutil.h"
44 #include "../betranshlp.h"
45 #include "bearch_arm_t.h"
46
47 #include "arm_nodes_attr.h"
48 #include "arm_transform.h"
49 #include "arm_optimize.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 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
58
59 /** hold the current code generator during transformation */
60 static arm_code_gen_t *env_cg;
61
62 static inline int mode_needs_gp_reg(ir_mode *mode)
63 {
64         return mode_is_int(mode) || mode_is_reference(mode);
65 }
66
67 /**
68  * Creates a possible DAG for an constant.
69  */
70 static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block,
71                                          unsigned int value)
72 {
73         ir_node *result;
74         arm_vals v, vn;
75         int cnt;
76
77         arm_gen_vals_from_word(value, &v);
78         arm_gen_vals_from_word(~value, &vn);
79
80         if (vn.ops < v.ops) {
81                 /* remove bits */
82                 result = new_bd_arm_Mvn_imm(dbgi, block, vn.values[0], vn.rors[0]);
83                 be_dep_on_frame(result);
84
85                 for (cnt = 1; cnt < vn.ops; ++cnt) {
86                         result = new_bd_arm_Bic_imm(dbgi, block, result,
87                                                     vn.values[cnt], vn.rors[cnt]);
88                 }
89         } else {
90                 /* add bits */
91                 result = new_bd_arm_Mov_imm(dbgi, block, v.values[0], v.rors[0]);
92                 be_dep_on_frame(result);
93
94                 for (cnt = 1; cnt < v.ops; ++cnt) {
95                         result = new_bd_arm_Or_imm(dbgi, block, result,
96                                                    v.values[cnt], v.rors[cnt]);
97                 }
98         }
99         return result;
100 }
101
102 /**
103  * Create a DAG constructing a given Const.
104  *
105  * @param irn  a Firm const
106  */
107 static ir_node *create_const_graph(ir_node *irn, ir_node *block)
108 {
109         tarval  *tv = get_Const_tarval(irn);
110         ir_mode *mode = get_tarval_mode(tv);
111         unsigned value;
112
113         if (mode_is_reference(mode)) {
114                 /* ARM is 32bit, so we can safely convert a reference tarval into Iu */
115                 assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_Iu));
116                 tv = tarval_convert_to(tv, mode_Iu);
117         }
118         value = get_tarval_long(tv);
119         return create_const_graph_value(get_irn_dbg_info(irn), block, value);
120 }
121
122 /**
123  * Create an And that will mask all upper bits
124  */
125 static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
126                                    int src_bits)
127 {
128         if (src_bits == 8) {
129                 return new_bd_arm_And_imm(dbgi, block, op, 0xFF, 0);
130         } else if (src_bits == 16) {
131                 ir_node *lshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, 16);
132                 ir_node *rshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift, ARM_SHF_LSR_IMM, 16);
133                 return rshift;
134         } else {
135                 panic("zero extension only supported for 8 and 16 bits");
136         }
137 }
138
139 /**
140  * Generate code for a sign extension.
141  */
142 static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
143                                    int src_bits)
144 {
145         int shift_width = 32 - src_bits;
146         ir_node *lshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, shift_width);
147         ir_node *rshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift_node, ARM_SHF_ASR_IMM, shift_width);
148         return rshift_node;
149 }
150
151 static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
152                               ir_mode *orig_mode)
153 {
154         int bits = get_mode_size_bits(orig_mode);
155         if (bits == 32)
156                 return op;
157
158         if (mode_is_signed(orig_mode)) {
159                 return gen_sign_extension(dbgi, block, op, bits);
160         } else {
161                 return gen_zero_extension(dbgi, block, op, bits);
162         }
163 }
164
165 /**
166  * returns true if it is assured, that the upper bits of a node are "clean"
167  * which means for a 16 or 8 bit value, that the upper bits in the register
168  * are 0 for unsigned and a copy of the last significant bit for signed
169  * numbers.
170  */
171 static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
172 {
173         (void) transformed_node;
174         (void) mode;
175         /* TODO */
176         return false;
177 }
178
179 /**
180  * Transforms a Conv node.
181  *
182  * @return The created ia32 Conv node
183  */
184 static ir_node *gen_Conv(ir_node *node) {
185         ir_node  *block    = be_transform_node(get_nodes_block(node));
186         ir_node  *op       = get_Conv_op(node);
187         ir_node  *new_op   = be_transform_node(op);
188         ir_mode  *src_mode = get_irn_mode(op);
189         ir_mode  *dst_mode = get_irn_mode(node);
190         dbg_info *dbg      = get_irn_dbg_info(node);
191
192         if (src_mode == dst_mode)
193                 return new_op;
194
195         if (mode_is_float(src_mode) || mode_is_float(dst_mode)) {
196                 env_cg->have_fp_insn = 1;
197
198                 if (USE_FPA(env_cg->isa)) {
199                         if (mode_is_float(src_mode)) {
200                                 if (mode_is_float(dst_mode)) {
201                                         /* from float to float */
202                                         return new_bd_arm_fpaMvf(dbg, block, new_op, dst_mode);
203                                 }
204                                 else {
205                                         /* from float to int */
206                                         return new_bd_arm_fpaFix(dbg, block, new_op, dst_mode);
207                                 }
208                         }
209                         else {
210                                 /* from int to float */
211                                 return new_bd_arm_fpaFlt(dbg, block, new_op, dst_mode);
212                         }
213                 } else if (USE_VFP(env_cg->isa)) {
214                         panic("VFP not supported yet");
215                         return NULL;
216                 } else {
217                         panic("Softfloat not supported yet");
218                         return NULL;
219                 }
220         } else { /* complete in gp registers */
221                 int src_bits = get_mode_size_bits(src_mode);
222                 int dst_bits = get_mode_size_bits(dst_mode);
223                 int min_bits;
224                 ir_mode *min_mode;
225
226                 if (src_bits == dst_bits) {
227                         /* kill unneccessary conv */
228                         return new_op;
229                 }
230
231                 if (src_bits < dst_bits) {
232                         min_bits = src_bits;
233                         min_mode = src_mode;
234                 } else {
235                         min_bits = dst_bits;
236                         min_mode = dst_mode;
237                 }
238
239                 if (upper_bits_clean(new_op, min_mode)) {
240                         return new_op;
241                 }
242
243                 if (mode_is_signed(min_mode)) {
244                         return gen_sign_extension(dbg, block, new_op, min_bits);
245                 } else {
246                         return gen_zero_extension(dbg, block, new_op, min_bits);
247                 }
248         }
249 }
250
251 typedef struct {
252         unsigned char  imm_8;
253         unsigned char  rot;
254 } arm_immediate_t;
255
256 static bool try_encode_as_immediate(const ir_node *node, arm_immediate_t *res)
257 {
258         unsigned val;
259
260         if (!is_Const(node))
261                 return false;
262
263         val = get_tarval_long(get_Const_tarval(node));
264
265         if (val == 0) {
266                 res->imm_8 = 0;
267                 res->rot   = 0;
268                 return true;
269         }
270         if (val <= 0xff) {
271                 res->imm_8 = val;
272                 res->rot   = 0;
273                 return true;
274         }
275         /* arm allows to use to rotate an 8bit immediate value by a multiple of 2
276            (= 0, 2, 4, 6, ...).
277            So we determine the smallest even position with a bit set
278            and the highest even position with no bit set anymore.
279            If the difference between these 2 is <= 8, then we can encode the value
280            as immediate.
281          */
282         unsigned low_pos  = ntz(val) & ~1u;
283         unsigned high_pos = (32-nlz(val)+1) & ~1u;
284
285         if (high_pos - low_pos <= 8) {
286                 res->imm_8 = val >> low_pos;
287                 res->rot   = 32 - low_pos;
288                 return true;
289         }
290
291         if (high_pos > 24) {
292                 res->rot = 34 - high_pos;
293                 val      = val >> (32-res->rot) | val << (res->rot);
294                 if (val <= 0xff) {
295                         res->imm_8 = val;
296                         return true;
297                 }
298         }
299
300         return false;
301 }
302
303 static int is_downconv(const ir_node *node)
304 {
305         ir_mode *src_mode;
306         ir_mode *dest_mode;
307
308         if (!is_Conv(node))
309                 return 0;
310
311         /* we only want to skip the conv when we're the only user
312          * (not optimal but for now...)
313          */
314         if (get_irn_n_edges(node) > 1)
315                 return 0;
316
317         src_mode  = get_irn_mode(get_Conv_op(node));
318         dest_mode = get_irn_mode(node);
319         return
320                 mode_needs_gp_reg(src_mode)  &&
321                 mode_needs_gp_reg(dest_mode) &&
322                 get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
323 }
324
325 static ir_node *arm_skip_downconv(ir_node *node)
326 {
327         while (is_downconv(node))
328                 node = get_Conv_op(node);
329         return node;
330 }
331
332 typedef enum {
333         MATCH_NONE         = 0,
334         MATCH_COMMUTATIVE  = 1 << 0,
335         MATCH_SIZE_NEUTRAL = 1 << 1,
336 } match_flags_t;
337
338 typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2);
339 typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, unsigned char imm8, unsigned char imm_rot);
340
341 static ir_node *gen_int_binop(ir_node *node, match_flags_t flags,
342                 new_binop_reg_func new_reg, new_binop_imm_func new_imm)
343 {
344         ir_node  *block   = be_transform_node(get_nodes_block(node));
345         ir_node  *op1     = get_binop_left(node);
346         ir_node  *new_op1;
347         ir_node  *op2     = get_binop_right(node);
348         ir_node  *new_op2;
349         dbg_info *dbgi    = get_irn_dbg_info(node);
350         arm_immediate_t imm;
351
352         if (flags & MATCH_SIZE_NEUTRAL) {
353                 op1 = arm_skip_downconv(op1);
354                 op2 = arm_skip_downconv(op2);
355         } else {
356                 assert(get_mode_size_bits(get_irn_mode(node)) == 32);
357         }
358
359         if (try_encode_as_immediate(op2, &imm)) {
360                 ir_node *new_op1 = be_transform_node(op1);
361                 return new_imm(dbgi, block, new_op1, imm.imm_8, imm.rot);
362         }
363         new_op2 = be_transform_node(op2);
364     if ((flags & MATCH_COMMUTATIVE) && try_encode_as_immediate(op1, &imm)) {
365                 return new_imm(dbgi, block, new_op2, imm.imm_8, imm.rot);
366         }
367         new_op1 = be_transform_node(op1);
368
369         return new_reg(dbgi, block, new_op1, new_op2);
370 }
371
372 /**
373  * Creates an ARM Add.
374  *
375  * @return the created arm Add node
376  */
377 static ir_node *gen_Add(ir_node *node)
378 {
379         ir_mode  *mode    = get_irn_mode(node);
380
381         if (mode_is_float(mode)) {
382                 ir_node  *block   = be_transform_node(get_nodes_block(node));
383                 ir_node  *op1     = get_Add_left(node);
384                 ir_node  *op2     = get_Add_right(node);
385                 dbg_info *dbgi    = get_irn_dbg_info(node);
386                 ir_node  *new_op1 = be_transform_node(op1);
387                 ir_node  *new_op2 = be_transform_node(op2);
388                 env_cg->have_fp_insn = 1;
389                 if (USE_FPA(env_cg->isa)) {
390 #if 0
391                         if (is_arm_fpaMvf_i(new_op1))
392                                 return new_bd_arm_fpaAdf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
393                         if (is_arm_fpaMvf_i(new_op2))
394                                 return new_bd_arm_fpaAdf_i(dbgi, block, new_op1, mode, get_arm_imm_value(new_op2));
395 #endif
396                         return new_bd_arm_fpaAdf(dbgi, block, new_op1, new_op2, mode);
397                 } else if (USE_VFP(env_cg->isa)) {
398                         assert(mode != mode_E && "IEEE Extended FP not supported");
399                         panic("VFP not supported yet");
400                         return NULL;
401                 }
402                 else {
403                         panic("Softfloat not supported yet");
404                         return NULL;
405                 }
406         } else {
407 #if 0
408                 /* check for MLA */
409                 if (is_arm_Mul(new_op1) && get_irn_n_edges(op1) == 1) {
410                         new_op3 = new_op2;
411                         new_op2 = get_irn_n(new_op1, 1);
412                         new_op1 = get_irn_n(new_op1, 0);
413
414                         return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
415                 }
416                 if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
417                         new_op3 = new_op1;
418                         new_op1 = get_irn_n(new_op2, 0);
419                         new_op2 = get_irn_n(new_op2, 1);
420
421                         return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
422                 }
423 #endif
424
425                 return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
426                                 new_bd_arm_Add_reg, new_bd_arm_Add_imm);
427         }
428 }
429
430 /**
431  * Creates an ARM Mul.
432  *
433  * @return the created arm Mul node
434  */
435 static ir_node *gen_Mul(ir_node *node) {
436         ir_node  *block   = be_transform_node(get_nodes_block(node));
437         ir_node  *op1     = get_Mul_left(node);
438         ir_node  *new_op1 = be_transform_node(op1);
439         ir_node  *op2     = get_Mul_right(node);
440         ir_node  *new_op2 = be_transform_node(op2);
441         ir_mode  *mode    = get_irn_mode(node);
442         dbg_info *dbg     = get_irn_dbg_info(node);
443
444         if (mode_is_float(mode)) {
445                 env_cg->have_fp_insn = 1;
446                 if (USE_FPA(env_cg->isa)) {
447 #if 0
448                         if (is_arm_Mov_i(new_op1))
449                                 return new_bd_arm_fpaMuf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
450                         if (is_arm_Mov_i(new_op2))
451                                 return new_bd_arm_fpaMuf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
452 #endif
453                         return new_bd_arm_fpaMuf(dbg, block, new_op1, new_op2, mode);
454                 }
455                 else if (USE_VFP(env_cg->isa)) {
456                         assert(mode != mode_E && "IEEE Extended FP not supported");
457                         panic("VFP not supported yet");
458                         return NULL;
459                 }
460                 else {
461                         panic("Softfloat not supported yet");
462                         return NULL;
463                 }
464         }
465         assert(mode_is_data(mode));
466         return new_bd_arm_Mul(dbg, block, new_op1, new_op2);
467 }
468
469 /**
470  * Creates an ARM floating point Div.
471  *
472  * @param env   The transformation environment
473  * @return the created arm fDiv node
474  */
475 static ir_node *gen_Quot(ir_node *node) {
476         ir_node  *block   = be_transform_node(get_nodes_block(node));
477         ir_node  *op1     = get_Quot_left(node);
478         ir_node  *new_op1 = be_transform_node(op1);
479         ir_node  *op2     = get_Quot_right(node);
480         ir_node  *new_op2 = be_transform_node(op2);
481         ir_mode  *mode    = get_irn_mode(node);
482         dbg_info *dbg     = get_irn_dbg_info(node);
483
484         assert(mode != mode_E && "IEEE Extended FP not supported");
485
486         env_cg->have_fp_insn = 1;
487         if (USE_FPA(env_cg->isa)) {
488 #if 0
489                 if (is_arm_Mov_i(new_op1))
490                         return new_bd_arm_fpaRdf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
491                 if (is_arm_Mov_i(new_op2))
492                         return new_bd_arm_fpaDvf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
493 #endif
494                 return new_bd_arm_fpaDvf(dbg, block, new_op1, new_op2, mode);
495         } else if (USE_VFP(env_cg->isa)) {
496                 assert(mode != mode_E && "IEEE Extended FP not supported");
497                 panic("VFP not supported yet");
498         }
499         else {
500                 panic("Softfloat not supported yet");
501                 return NULL;
502         }
503 }
504
505 /**
506  * Creates an ARM And.
507  *
508  * @return the created arm And node
509  */
510 static ir_node *gen_And(ir_node *node)
511 {
512         return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
513                         new_bd_arm_And_reg, new_bd_arm_And_imm);
514 }
515
516 /**
517  * Creates an ARM Orr.
518  *
519  * @param env   The transformation environment
520  * @return the created arm Or node
521  */
522 static ir_node *gen_Or(ir_node *node)
523 {
524         return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
525                         new_bd_arm_Or_reg, new_bd_arm_Or_imm);
526 }
527
528 /**
529  * Creates an ARM Eor.
530  *
531  * @return the created arm Eor node
532  */
533 static ir_node *gen_Eor(ir_node *node)
534 {
535         return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
536                         new_bd_arm_Eor_reg, new_bd_arm_Eor_imm);
537 }
538
539 /**
540  * Creates an ARM Sub.
541  *
542  * @return the created arm Sub node
543  */
544 static ir_node *gen_Sub(ir_node *node)
545 {
546         ir_node  *block   = be_transform_node(get_nodes_block(node));
547         ir_node  *op1     = get_Sub_left(node);
548         ir_node  *new_op1 = be_transform_node(op1);
549         ir_node  *op2     = get_Sub_right(node);
550         ir_node  *new_op2 = be_transform_node(op2);
551         ir_mode  *mode    = get_irn_mode(node);
552         dbg_info *dbgi    = get_irn_dbg_info(node);
553
554         if (mode_is_float(mode)) {
555                 env_cg->have_fp_insn = 1;
556                 if (USE_FPA(env_cg->isa)) {
557 #if 0
558                         if (is_arm_Mov_i(new_op1))
559                                 return new_bd_arm_fpaRsf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
560                         if (is_arm_Mov_i(new_op2))
561                                 return new_bd_arm_fpaSuf_i(dbgi, block, new_op1, mode, get_arm_imm_value(new_op2));
562 #endif
563                         return new_bd_arm_fpaSuf(dbgi, block, new_op1, new_op2, mode);
564                 } else if (USE_VFP(env_cg->isa)) {
565                         assert(mode != mode_E && "IEEE Extended FP not supported");
566                         panic("VFP not supported yet");
567                         return NULL;
568                 } else {
569                         panic("Softfloat not supported yet");
570                         return NULL;
571                 }
572         } else {
573                 return gen_int_binop(node, MATCH_SIZE_NEUTRAL,
574                                 new_bd_arm_Sub_reg, new_bd_arm_Sub_imm);
575         }
576 }
577
578 static ir_node *make_shift(ir_node *node, match_flags_t flags,
579                 arm_shift_modifier shift_modifier)
580 {
581         ir_node  *block   = be_transform_node(get_nodes_block(node));
582         ir_node  *op1     = get_binop_left(node);
583         ir_node  *op2     = get_binop_right(node);
584         dbg_info *dbgi    = get_irn_dbg_info(node);
585         ir_node  *new_op1;
586         ir_node  *new_op2;
587
588         if (flags & MATCH_SIZE_NEUTRAL) {
589                 op1 = arm_skip_downconv(op1);
590                 op2 = arm_skip_downconv(op2);
591         }
592         new_op1 = be_transform_node(op1);
593         new_op2 = be_transform_node(op2);
594         return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2, shift_modifier);
595 }
596
597 /**
598  * Creates an ARM Shl.
599  *
600  * @return the created ARM Shl node
601  */
602 static ir_node *gen_Shl(ir_node *node)
603 {
604         return make_shift(node, MATCH_SIZE_NEUTRAL, ARM_SHF_LSL_REG);
605 }
606
607 /**
608  * Creates an ARM Shr.
609  *
610  * @return the created ARM Shr node
611  */
612 static ir_node *gen_Shr(ir_node *node)
613 {
614         return make_shift(node, MATCH_NONE, ARM_SHF_LSR_REG);
615 }
616
617 /**
618  * Creates an ARM Shrs.
619  *
620  * @return the created ARM Shrs node
621  */
622 static ir_node *gen_Shrs(ir_node *node)
623 {
624         return make_shift(node, MATCH_NONE, ARM_SHF_ASR_REG);
625 }
626
627 /**
628  * Creates an ARM Ror.
629  *
630  * @return the created ARM Ror node
631  */
632 static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2)
633 {
634         ir_node  *block   = be_transform_node(get_nodes_block(node));
635         ir_node  *new_op1 = be_transform_node(op1);
636         dbg_info *dbgi    = get_irn_dbg_info(node);
637         ir_node  *new_op2 = be_transform_node(op2);
638
639         return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
640                                             ARM_SHF_ROR_REG);
641 }
642
643 /**
644  * Creates an ARM Rol.
645  *
646  * @return the created ARM Rol node
647  *
648  * Note: there is no Rol on arm, we have to use Ror
649  */
650 static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2)
651 {
652         ir_node  *block   = be_transform_node(get_nodes_block(node));
653         ir_node  *new_op1 = be_transform_node(op1);
654         dbg_info *dbgi    = get_irn_dbg_info(node);
655         ir_node  *new_op2 = be_transform_node(op2);
656
657         new_op2 = new_bd_arm_Rsb_imm(dbgi, block, new_op2, 32, 0);
658         return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
659                                             ARM_SHF_ROR_REG);
660 }
661
662 /**
663  * Creates an ARM ROR from a Firm Rotl.
664  *
665  * @return the created ARM Ror node
666  */
667 static ir_node *gen_Rotl(ir_node *node)
668 {
669         ir_node *rotate = NULL;
670         ir_node *op1    = get_Rotl_left(node);
671         ir_node *op2    = get_Rotl_right(node);
672
673         /* Firm has only RotL, so we are looking for a right (op2)
674            operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
675            that means we can create a RotR. */
676
677         if (is_Add(op2)) {
678                 ir_node *right = get_Add_right(op2);
679                 if (is_Const(right)) {
680                         tarval  *tv   = get_Const_tarval(right);
681                         ir_mode *mode = get_irn_mode(node);
682                         long     bits = get_mode_size_bits(mode);
683                         ir_node *left = get_Add_left(op2);
684
685                         if (is_Minus(left) &&
686                             tarval_is_long(tv)          &&
687                             get_tarval_long(tv) == bits &&
688                             bits                == 32)
689                                 rotate = gen_Ror(node, op1, get_Minus_op(left));
690                 }
691         } else if (is_Sub(op2)) {
692                 ir_node *left = get_Sub_left(op2);
693                 if (is_Const(left)) {
694                         tarval  *tv   = get_Const_tarval(left);
695                         ir_mode *mode = get_irn_mode(node);
696                         long     bits = get_mode_size_bits(mode);
697                         ir_node *right = get_Sub_right(op2);
698
699                         if (tarval_is_long(tv)          &&
700                             get_tarval_long(tv) == bits &&
701                             bits                == 32)
702                                 rotate = gen_Ror(node, op1, right);
703                 }
704         } else if (is_Const(op2)) {
705                 tarval  *tv   = get_Const_tarval(op2);
706                 ir_mode *mode = get_irn_mode(node);
707                 long     bits = get_mode_size_bits(mode);
708
709                 if (tarval_is_long(tv) && bits == 32) {
710                         ir_node  *block   = be_transform_node(get_nodes_block(node));
711                         ir_node  *new_op1 = be_transform_node(op1);
712                         dbg_info *dbgi    = get_irn_dbg_info(node);
713
714                         bits = (bits - get_tarval_long(tv)) & 31;
715                         rotate = new_bd_arm_Mov_reg_shift_imm(dbgi, block, new_op1, ARM_SHF_ROR_IMM, bits);
716                 }
717         }
718
719         if (rotate == NULL) {
720                 rotate = gen_Rol(node, op1, op2);
721         }
722
723         return rotate;
724 }
725
726 /**
727  * Transforms a Not node.
728  *
729  * @return the created ARM Not node
730  */
731 static ir_node *gen_Not(ir_node *node)
732 {
733         ir_node  *block   = be_transform_node(get_nodes_block(node));
734         ir_node  *op      = get_Not_op(node);
735         ir_node  *new_op  = be_transform_node(op);
736         dbg_info *dbgi    = get_irn_dbg_info(node);
737
738         /* TODO: we could do alot more here with all the Mvn variations */
739
740         return new_bd_arm_Mvn_reg(dbgi, block, new_op);
741 }
742
743 /**
744  * Transforms an Abs node.
745  *
746  * @param env   The transformation environment
747  * @return the created ARM Abs node
748  */
749 static ir_node *gen_Abs(ir_node *node)
750 {
751         ir_node  *block   = be_transform_node(get_nodes_block(node));
752         ir_node  *op      = get_Abs_op(node);
753         ir_node  *new_op  = be_transform_node(op);
754         dbg_info *dbgi    = get_irn_dbg_info(node);
755         ir_mode  *mode    = get_irn_mode(node);
756
757         if (mode_is_float(mode)) {
758                 env_cg->have_fp_insn = 1;
759                 if (USE_FPA(env_cg->isa))
760                         return new_bd_arm_fpaAbs(dbgi, block, new_op, mode);
761                 else if (USE_VFP(env_cg->isa)) {
762                         assert(mode != mode_E && "IEEE Extended FP not supported");
763                         panic("VFP not supported yet");
764                 }
765                 else {
766                         panic("Softfloat not supported yet");
767                 }
768         }
769         assert(mode_is_data(mode));
770         return new_bd_arm_Abs(dbgi, block, new_op);
771 }
772
773 /**
774  * Transforms a Minus node.
775  *
776  * @return the created ARM Minus node
777  */
778 static ir_node *gen_Minus(ir_node *node)
779 {
780         ir_node  *block   = be_transform_node(get_nodes_block(node));
781         ir_node  *op      = get_Minus_op(node);
782         ir_node  *new_op  = be_transform_node(op);
783         dbg_info *dbgi    = get_irn_dbg_info(node);
784         ir_mode  *mode    = get_irn_mode(node);
785
786         if (mode_is_float(mode)) {
787                 env_cg->have_fp_insn = 1;
788                 if (USE_FPA(env_cg->isa))
789                         return new_bd_arm_fpaMvf(dbgi, block, op, mode);
790                 else if (USE_VFP(env_cg->isa)) {
791                         assert(mode != mode_E && "IEEE Extended FP not supported");
792                         panic("VFP not supported yet");
793                 }
794                 else {
795                         panic("Softfloat not supported yet");
796                 }
797         }
798         assert(mode_is_data(mode));
799         return new_bd_arm_Rsb_imm(dbgi, block, new_op, 0, 0);
800 }
801
802 /**
803  * Transforms a Load.
804  *
805  * @return the created ARM Load node
806  */
807 static ir_node *gen_Load(ir_node *node) {
808         ir_node  *block    = be_transform_node(get_nodes_block(node));
809         ir_node  *ptr      = get_Load_ptr(node);
810         ir_node  *new_ptr  = be_transform_node(ptr);
811         ir_node  *mem      = get_Load_mem(node);
812         ir_node  *new_mem  = be_transform_node(mem);
813         ir_mode  *mode     = get_Load_mode(node);
814         dbg_info *dbgi      = get_irn_dbg_info(node);
815         ir_node  *new_load = NULL;
816
817         if (mode_is_float(mode)) {
818                 env_cg->have_fp_insn = 1;
819                 if (USE_FPA(env_cg->isa))
820                         new_load = new_bd_arm_fpaLdf(dbgi, block, new_ptr, new_mem, mode);
821                 else if (USE_VFP(env_cg->isa)) {
822                         assert(mode != mode_E && "IEEE Extended FP not supported");
823                         panic("VFP not supported yet");
824                 } else {
825                         panic("Softfloat not supported yet");
826                 }
827         } else {
828                 assert(mode_is_data(mode) && "unsupported mode for Load");
829
830                 new_load = new_bd_arm_Ldr(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false);
831         }
832         set_irn_pinned(new_load, get_irn_pinned(node));
833
834         /* check for special case: the loaded value might not be used */
835         if (be_get_Proj_for_pn(node, pn_Load_res) == NULL) {
836                 /* add a result proj and a Keep to produce a pseudo use */
837                 ir_node *proj = new_r_Proj(block, new_load, mode_Iu, pn_arm_Ldr_res);
838                 be_new_Keep(block, 1, &proj);
839         }
840
841         return new_load;
842 }
843
844 /**
845  * Transforms a Store.
846  *
847  * @return the created ARM Store node
848  */
849 static ir_node *gen_Store(ir_node *node)
850 {
851         ir_node  *block    = be_transform_node(get_nodes_block(node));
852         ir_node  *ptr      = get_Store_ptr(node);
853         ir_node  *new_ptr  = be_transform_node(ptr);
854         ir_node  *mem      = get_Store_mem(node);
855         ir_node  *new_mem  = be_transform_node(mem);
856         ir_node  *val      = get_Store_value(node);
857         ir_node  *new_val  = be_transform_node(val);
858         ir_mode  *mode     = get_irn_mode(val);
859         dbg_info *dbgi     = get_irn_dbg_info(node);
860         ir_node *new_store = NULL;
861
862         if (mode_is_float(mode)) {
863                 env_cg->have_fp_insn = 1;
864                 if (USE_FPA(env_cg->isa))
865                         new_store = new_bd_arm_fpaStf(dbgi, block, new_ptr, new_val,
866                                                       new_mem, mode);
867                 else if (USE_VFP(env_cg->isa)) {
868                         assert(mode != mode_E && "IEEE Extended FP not supported");
869                         panic("VFP not supported yet");
870                 } else {
871                         panic("Softfloat not supported yet");
872                 }
873         } else {
874                 assert(mode_is_data(mode) && "unsupported mode for Store");
875                 new_store = new_bd_arm_Str(dbgi, block, new_ptr, new_val, new_mem, mode,
876                                            NULL, 0, 0, false);
877         }
878         set_irn_pinned(new_store, get_irn_pinned(node));
879         return new_store;
880 }
881
882 static ir_node *gen_Jmp(ir_node *node)
883 {
884         ir_node  *block     = get_nodes_block(node);
885         ir_node  *new_block = be_transform_node(block);
886         dbg_info *dbgi      = get_irn_dbg_info(node);
887
888         return new_bd_arm_Jmp(dbgi, new_block);
889 }
890
891 static ir_node *gen_be_Call(ir_node *node)
892 {
893         ir_node *res = be_duplicate_node(node);
894         arch_irn_add_flags(res, arch_irn_flags_modify_flags);
895
896         return res;
897 }
898
899 static ir_node *gen_SwitchJmp(ir_node *node)
900 {
901         ir_node  *block    = be_transform_node(get_nodes_block(node));
902         ir_node  *selector = get_Cond_selector(node);
903         dbg_info *dbgi     = get_irn_dbg_info(node);
904         ir_node *new_op = be_transform_node(selector);
905         ir_node *const_graph;
906         ir_node *sub;
907
908         ir_node *proj;
909         const ir_edge_t *edge;
910         int min = INT_MAX;
911         int max = INT_MIN;
912         int translation;
913         int pn;
914         int n_projs;
915
916         foreach_out_edge(node, edge) {
917                 proj = get_edge_src_irn(edge);
918                 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
919
920                 pn = get_Proj_proj(proj);
921
922                 min = pn<min ? pn : min;
923                 max = pn>max ? pn : max;
924         }
925         translation = min;
926         n_projs = max - translation + 1;
927
928         foreach_out_edge(node, edge) {
929                 proj = get_edge_src_irn(edge);
930                 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
931
932                 pn = get_Proj_proj(proj) - translation;
933                 set_Proj_proj(proj, pn);
934         }
935
936         const_graph = create_const_graph_value(dbgi, block, translation);
937         sub = new_bd_arm_Sub_reg(dbgi, block, new_op, const_graph);
938         return new_bd_arm_SwitchJmp(dbgi, block, sub, n_projs, get_Cond_default_proj(node) - translation);
939 }
940
941 static ir_node *gen_Cmp(ir_node *node)
942 {
943         ir_node  *block    = be_transform_node(get_nodes_block(node));
944         ir_node  *op1      = get_Cmp_left(node);
945         ir_node  *op2      = get_Cmp_right(node);
946         ir_mode  *cmp_mode = get_irn_mode(op1);
947         dbg_info *dbgi     = get_irn_dbg_info(node);
948         ir_node  *new_op1;
949         ir_node  *new_op2;
950         bool      is_unsigned;
951
952         if (mode_is_float(cmp_mode)) {
953                 /* TODO: revivie this code */
954                 panic("FloatCmp NIY");
955 #if 0
956                 ir_node *new_op2  = be_transform_node(op2);
957                 /* floating point compare */
958                 pn_Cmp pnc = get_Proj_proj(selector);
959
960                 if (pnc & pn_Cmp_Uo) {
961                         /* check for unordered, need cmf */
962                         return new_bd_arm_fpaCmfBra(dbgi, block, new_op1, new_op2, pnc);
963                 }
964                 /* Hmm: use need cmfe */
965                 return new_bd_arm_fpaCmfeBra(dbgi, block, new_op1, new_op2, pnc);
966 #endif
967         }
968
969         assert(get_irn_mode(op2) == cmp_mode);
970         is_unsigned = !mode_is_signed(cmp_mode);
971
972         /* compare with 0 can be done with Tst */
973         if (is_Const(op2) && tarval_is_null(get_Const_tarval(op2))) {
974                 new_op1 = be_transform_node(op1);
975                 new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
976                 return new_bd_arm_Tst_reg(dbgi, block, new_op1, new_op1, false,
977                                           is_unsigned);
978         }
979         if (is_Const(op1) && tarval_is_null(get_Const_tarval(op1))) {
980                 new_op2 = be_transform_node(op2);
981                 new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode);
982                 return new_bd_arm_Tst_reg(dbgi, block, new_op2, new_op2, true,
983                                           is_unsigned);
984         }
985
986         /* integer compare, TODO: use shifer_op in all its combinations */
987         new_op1 = be_transform_node(op1);
988         new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
989         new_op2 = be_transform_node(op2);
990         new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode);
991         return new_bd_arm_Cmp_reg(dbgi, block, new_op1, new_op2, false,
992                                   is_unsigned);
993 }
994
995 /**
996  * Transforms a Cond.
997  *
998  * @return the created ARM Cond node
999  */
1000 static ir_node *gen_Cond(ir_node *node)
1001 {
1002         ir_node  *selector = get_Cond_selector(node);
1003         ir_mode  *mode     = get_irn_mode(selector);
1004         ir_node  *block;
1005         ir_node  *flag_node;
1006         dbg_info *dbgi;
1007
1008         if (mode != mode_b) {
1009                 return gen_SwitchJmp(node);
1010         }
1011         assert(is_Proj(selector));
1012
1013         block     = be_transform_node(get_nodes_block(node));
1014         dbgi      = get_irn_dbg_info(node);
1015         flag_node = be_transform_node(get_Proj_pred(selector));
1016
1017         return new_bd_arm_B(dbgi, block, flag_node, get_Proj_proj(selector));
1018 }
1019
1020 static tarval *fpa_imm[3][fpa_max];
1021
1022 #if 0
1023 /**
1024  * Check, if a floating point tarval is an fpa immediate, i.e.
1025  * one of 0, 1, 2, 3, 4, 5, 10, or 0.5.
1026  */
1027 static int is_fpa_immediate(tarval *tv)
1028 {
1029         ir_mode *mode = get_tarval_mode(tv);
1030         int i, j, res = 1;
1031
1032         switch (get_mode_size_bits(mode)) {
1033         case 32:
1034                 i = 0;
1035                 break;
1036         case 64:
1037                 i = 1;
1038                 break;
1039         default:
1040                 i = 2;
1041         }
1042
1043         if (tarval_cmp(tv, get_tarval_null(mode)) & pn_Cmp_Lt) {
1044                 tv = tarval_neg(tv);
1045                 res = -1;
1046         }
1047
1048         for (j = 0; j < fpa_max; ++j) {
1049                 if (tv == fpa_imm[i][j])
1050                         return res * j;
1051         }
1052         return fpa_max;
1053 }
1054 #endif
1055
1056 /**
1057  * Transforms a Const node.
1058  *
1059  * @return The transformed ARM node.
1060  */
1061 static ir_node *gen_Const(ir_node *node) {
1062         ir_node  *block = be_transform_node(get_nodes_block(node));
1063         ir_mode *mode = get_irn_mode(node);
1064         dbg_info *dbg = get_irn_dbg_info(node);
1065
1066         if (mode_is_float(mode)) {
1067                 env_cg->have_fp_insn = 1;
1068                 if (USE_FPA(env_cg->isa)) {
1069                         tarval *tv = get_Const_tarval(node);
1070 #if 0
1071                         int imm = is_fpa_immediate(tv);
1072
1073                         if (imm != fpa_max) {
1074                                 if (imm > 0)
1075                                         node = new_bd_arm_fpaMvf_i(dbg, block, mode, imm);
1076                                 else
1077                                         node = new_bd_arm_fpaMnf_i(dbg, block, mode, -imm);
1078                         } else {
1079 #endif
1080                         {
1081                                 node = new_bd_arm_fpaConst(dbg, block, tv);
1082                         }
1083                         be_dep_on_frame(node);
1084                         return node;
1085                 }
1086                 else if (USE_VFP(env_cg->isa)) {
1087                         assert(mode != mode_E && "IEEE Extended FP not supported");
1088                         panic("VFP not supported yet");
1089                 }
1090                 else {
1091                         panic("Softfloat not supported yet");
1092                 }
1093         }
1094         return create_const_graph(node, block);
1095 }
1096
1097 /**
1098  * Transforms a SymConst node.
1099  *
1100  * @return The transformed ARM node.
1101  */
1102 static ir_node *gen_SymConst(ir_node *node)
1103 {
1104         ir_node   *block  = be_transform_node(get_nodes_block(node));
1105         ir_entity *entity = get_SymConst_entity(node);
1106         dbg_info  *dbgi   = get_irn_dbg_info(node);
1107         ir_node   *new_node;
1108
1109         new_node = new_bd_arm_SymConst(dbgi, block, entity);
1110         be_dep_on_frame(new_node);
1111         return new_node;
1112 }
1113
1114 /**
1115  * Transforms a CopyB node.
1116  *
1117  * @return The transformed ARM node.
1118  */
1119 static ir_node *gen_CopyB(ir_node *node) {
1120         ir_node  *block    = be_transform_node(get_nodes_block(node));
1121         ir_node  *src      = get_CopyB_src(node);
1122         ir_node  *new_src  = be_transform_node(src);
1123         ir_node  *dst      = get_CopyB_dst(node);
1124         ir_node  *new_dst  = be_transform_node(dst);
1125         ir_node  *mem      = get_CopyB_mem(node);
1126         ir_node  *new_mem  = be_transform_node(mem);
1127         dbg_info *dbg      = get_irn_dbg_info(node);
1128         int      size      = get_type_size_bytes(get_CopyB_type(node));
1129         ir_node  *src_copy;
1130         ir_node  *dst_copy;
1131
1132         src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], block, new_src);
1133         dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], block, new_dst);
1134
1135         return new_bd_arm_CopyB(dbg, block, dst_copy, src_copy,
1136                         new_bd_arm_EmptyReg(dbg, block),
1137                         new_bd_arm_EmptyReg(dbg, block),
1138                         new_bd_arm_EmptyReg(dbg, block),
1139                         new_mem, size);
1140 }
1141
1142 /**
1143  * Transforms a FrameAddr into an ARM Add.
1144  */
1145 static ir_node *gen_be_FrameAddr(ir_node *node)
1146 {
1147         ir_node   *block  = be_transform_node(get_nodes_block(node));
1148         ir_entity *ent    = be_get_frame_entity(node);
1149         ir_node   *fp     = be_get_FrameAddr_frame(node);
1150         ir_node   *new_fp = be_transform_node(fp);
1151         dbg_info  *dbgi   = get_irn_dbg_info(node);
1152         ir_node   *new_node;
1153
1154         new_node = new_bd_arm_FrameAddr(dbgi, block, new_fp, ent);
1155         return new_node;
1156 }
1157
1158 /**
1159  * Transform a be_AddSP into an arm_AddSP. Eat up const sizes.
1160  */
1161 static ir_node *gen_be_AddSP(ir_node *node) {
1162         ir_node  *block  = be_transform_node(get_nodes_block(node));
1163         ir_node  *sz     = get_irn_n(node, be_pos_AddSP_size);
1164         ir_node  *new_sz = be_transform_node(sz);
1165         ir_node  *sp     = get_irn_n(node, be_pos_AddSP_old_sp);
1166         ir_node  *new_sp = be_transform_node(sp);
1167         dbg_info *dbgi   = get_irn_dbg_info(node);
1168         ir_node  *nomem  = new_NoMem();
1169         ir_node  *new_op;
1170
1171         /* ARM stack grows in reverse direction, make a SubSPandCopy */
1172         new_op = new_bd_arm_SubSPandCopy(dbgi, block, new_sp, new_sz, nomem);
1173
1174         return new_op;
1175 }
1176
1177 /**
1178  * Transform a be_SubSP into an arm_SubSP. Eat up const sizes.
1179  */
1180 static ir_node *gen_be_SubSP(ir_node *node) {
1181         ir_node  *block  = be_transform_node(get_nodes_block(node));
1182         ir_node  *sz     = get_irn_n(node, be_pos_SubSP_size);
1183         ir_node  *new_sz = be_transform_node(sz);
1184         ir_node  *sp     = get_irn_n(node, be_pos_SubSP_old_sp);
1185         ir_node  *new_sp = be_transform_node(sp);
1186         dbg_info *dbgi   = get_irn_dbg_info(node);
1187         ir_node  *nomem  = new_NoMem();
1188         ir_node  *new_op;
1189
1190         /* ARM stack grows in reverse direction, make an AddSP */
1191         new_op = new_bd_arm_AddSP(dbgi, block, new_sp, new_sz, nomem);
1192
1193         return new_op;
1194 }
1195
1196 /**
1197  * Transform a be_Copy.
1198  */
1199 static ir_node *gen_be_Copy(ir_node *node) {
1200         ir_node *result = be_duplicate_node(node);
1201         ir_mode *mode   = get_irn_mode(result);
1202
1203         if (mode_needs_gp_reg(mode)) {
1204                 set_irn_mode(node, mode_Iu);
1205         }
1206
1207         return result;
1208 }
1209
1210 /**
1211  * Transform a Proj from a Load.
1212  */
1213 static ir_node *gen_Proj_Load(ir_node *node) {
1214         ir_node  *block    = be_transform_node(get_nodes_block(node));
1215         ir_node  *load     = get_Proj_pred(node);
1216         ir_node  *new_load = be_transform_node(load);
1217         dbg_info *dbgi     = get_irn_dbg_info(node);
1218         long     proj      = get_Proj_proj(node);
1219
1220         /* renumber the proj */
1221         switch (get_arm_irn_opcode(new_load)) {
1222         case iro_arm_Ldr:
1223                 /* handle all gp loads equal: they have the same proj numbers. */
1224                 if (proj == pn_Load_res) {
1225                         return new_rd_Proj(dbgi, block, new_load, mode_Iu, pn_arm_Ldr_res);
1226                 } else if (proj == pn_Load_M) {
1227                         return new_rd_Proj(dbgi, block, new_load, mode_M, pn_arm_Ldr_M);
1228                 }
1229                 break;
1230         case iro_arm_fpaLdf:
1231                 if (proj == pn_Load_res) {
1232                         ir_mode *mode = get_Load_mode(load);
1233                         return new_rd_Proj(dbgi, block, new_load, mode, pn_arm_fpaLdf_res);
1234                 } else if (proj == pn_Load_M) {
1235                         return new_rd_Proj(dbgi, block, new_load, mode_M, pn_arm_fpaLdf_M);
1236                 }
1237                 break;
1238         default:
1239                 break;
1240         }
1241         panic("Unsupported Proj from Load");
1242 }
1243
1244 /**
1245  * Transform and renumber the Projs from a CopyB.
1246  */
1247 static ir_node *gen_Proj_CopyB(ir_node *node) {
1248         ir_node  *block    = be_transform_node(get_nodes_block(node));
1249         ir_node  *pred     = get_Proj_pred(node);
1250         ir_node  *new_pred = be_transform_node(pred);
1251         dbg_info *dbgi     = get_irn_dbg_info(node);
1252         long     proj      = get_Proj_proj(node);
1253
1254         switch(proj) {
1255         case pn_CopyB_M_regular:
1256                 if (is_arm_CopyB(new_pred)) {
1257                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_CopyB_M);
1258                 }
1259                 break;
1260         default:
1261                 break;
1262         }
1263         panic("Unsupported Proj from CopyB");
1264 }
1265
1266 /**
1267  * Transform and renumber the Projs from a Quot.
1268  */
1269 static ir_node *gen_Proj_Quot(ir_node *node) {
1270         ir_node  *block    = be_transform_node(get_nodes_block(node));
1271         ir_node  *pred     = get_Proj_pred(node);
1272         ir_node  *new_pred = be_transform_node(pred);
1273         dbg_info *dbgi     = get_irn_dbg_info(node);
1274         ir_mode  *mode     = get_irn_mode(node);
1275         long     proj      = get_Proj_proj(node);
1276
1277         switch (proj) {
1278         case pn_Quot_M:
1279                 if (is_arm_fpaDvf(new_pred)) {
1280                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaDvf_M);
1281                 } else if (is_arm_fpaRdf(new_pred)) {
1282                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaRdf_M);
1283                 } else if (is_arm_fpaFdv(new_pred)) {
1284                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaFdv_M);
1285                 } else if (is_arm_fpaFrd(new_pred)) {
1286                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaFrd_M);
1287                 }
1288                 break;
1289         case pn_Quot_res:
1290                 if (is_arm_fpaDvf(new_pred)) {
1291                         return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaDvf_res);
1292                 } else if (is_arm_fpaRdf(new_pred)) {
1293                         return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaRdf_res);
1294                 } else if (is_arm_fpaFdv(new_pred)) {
1295                         return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaFdv_res);
1296                 } else if (is_arm_fpaFrd(new_pred)) {
1297                         return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaFrd_res);
1298                 }
1299                 break;
1300         default:
1301                 break;
1302         }
1303         panic("Unsupported Proj from Quot");
1304 }
1305
1306 /**
1307  * Transform the Projs of a be_AddSP.
1308  */
1309 static ir_node *gen_Proj_be_AddSP(ir_node *node) {
1310         ir_node  *block    = be_transform_node(get_nodes_block(node));
1311         ir_node  *pred     = get_Proj_pred(node);
1312         ir_node  *new_pred = be_transform_node(pred);
1313         dbg_info *dbgi     = get_irn_dbg_info(node);
1314         long     proj      = get_Proj_proj(node);
1315
1316         if (proj == pn_be_AddSP_sp) {
1317                 ir_node *res = new_rd_Proj(dbgi, block, new_pred, mode_Iu,
1318                                            pn_arm_SubSPandCopy_stack);
1319                 arch_set_irn_register(res, &arm_gp_regs[REG_SP]);
1320                 return res;
1321         } else if(proj == pn_be_AddSP_res) {
1322                 return new_rd_Proj(dbgi, block, new_pred, mode_Iu, pn_arm_SubSPandCopy_addr);
1323         } else if (proj == pn_be_AddSP_M) {
1324                 return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_SubSPandCopy_M);
1325         }
1326         panic("Unsupported Proj from AddSP");
1327 }
1328
1329 /**
1330  * Transform the Projs of a be_SubSP.
1331  */
1332 static ir_node *gen_Proj_be_SubSP(ir_node *node) {
1333         ir_node  *block    = be_transform_node(get_nodes_block(node));
1334         ir_node  *pred     = get_Proj_pred(node);
1335         ir_node  *new_pred = be_transform_node(pred);
1336         dbg_info *dbgi     = get_irn_dbg_info(node);
1337         long     proj      = get_Proj_proj(node);
1338
1339         if (proj == pn_be_SubSP_sp) {
1340                 ir_node *res = new_rd_Proj(dbgi, block, new_pred, mode_Iu,
1341                                            pn_arm_AddSP_stack);
1342                 arch_set_irn_register(res, &arm_gp_regs[REG_SP]);
1343                 return res;
1344         } else if (proj == pn_be_SubSP_M) {
1345                 return new_rd_Proj(dbgi,  block, new_pred, mode_M, pn_arm_AddSP_M);
1346         }
1347         panic("Unsupported Proj from SubSP");
1348 }
1349
1350 /**
1351  * Transform the Projs from a Cmp.
1352  */
1353 static ir_node *gen_Proj_Cmp(ir_node *node) {
1354         (void) node;
1355         panic("Mux NYI");
1356 }
1357
1358
1359 /**
1360  * Transform the Thread Local Storage Proj.
1361  */
1362 static ir_node *gen_Proj_tls(ir_node *node) {
1363         ir_node  *block = be_transform_node(get_nodes_block(node));
1364         dbg_info *dbgi  = NULL;
1365
1366         return new_bd_arm_LdTls(dbgi, block, mode_Iu);
1367 }
1368
1369 /**
1370  * Transform a Proj node.
1371  */
1372 static ir_node *gen_Proj(ir_node *node) {
1373         ir_graph *irg  = current_ir_graph;
1374         dbg_info *dbgi = get_irn_dbg_info(node);
1375         ir_node  *pred = get_Proj_pred(node);
1376         long     proj  = get_Proj_proj(node);
1377
1378         if (is_Store(pred)) {
1379                 if (proj == pn_Store_M) {
1380                         return be_transform_node(pred);
1381                 } else {
1382                         panic("Unsupported Proj from Store");
1383                 }
1384         } else if (is_Load(pred)) {
1385                 return gen_Proj_Load(node);
1386         } else if (is_CopyB(pred)) {
1387                 return gen_Proj_CopyB(node);
1388         } else if (is_Quot(pred)) {
1389                 return gen_Proj_Quot(node);
1390         } else if (be_is_SubSP(pred)) {
1391                 return gen_Proj_be_SubSP(node);
1392         } else if (be_is_AddSP(pred)) {
1393                 return gen_Proj_be_AddSP(node);
1394         } else if (is_Cmp(pred)) {
1395                 return gen_Proj_Cmp(node);
1396         } else if (is_Start(pred)) {
1397                 if (proj == pn_Start_X_initial_exec) {
1398                         ir_node *block = get_nodes_block(pred);
1399                         ir_node *jump;
1400
1401                         /* we exchange the ProjX with a jump */
1402                         block = be_transform_node(block);
1403                         jump  = new_rd_Jmp(dbgi, block);
1404                         return jump;
1405                 }
1406                 if (node == get_irg_anchor(irg, anchor_tls)) {
1407                         return gen_Proj_tls(node);
1408                 }
1409         } else {
1410                 ir_node *new_pred = be_transform_node(pred);
1411                 ir_mode *mode     = get_irn_mode(node);
1412                 if (mode_needs_gp_reg(mode)) {
1413                         ir_node *block    = be_transform_node(get_nodes_block(node));
1414                         ir_node *new_proj = new_r_Proj(block, new_pred, mode_Iu,
1415                                                        get_Proj_proj(node));
1416                         new_proj->node_nr = node->node_nr;
1417                         return new_proj;
1418                 }
1419         }
1420
1421         return be_duplicate_node(node);
1422 }
1423
1424 typedef ir_node *(*create_const_node_func)(dbg_info *db, ir_node *block);
1425
1426 static inline ir_node *create_const(ir_node **place,
1427                                     create_const_node_func func,
1428                                     const arch_register_t* reg)
1429 {
1430         ir_node *block, *res;
1431
1432         if (*place != NULL)
1433                 return *place;
1434
1435         block = get_irg_start_block(env_cg->irg);
1436         res = func(NULL, block);
1437         arch_set_irn_register(res, reg);
1438         *place = res;
1439         return res;
1440 }
1441
1442 static ir_node *gen_Unknown(ir_node *node)
1443 {
1444         ir_node  *block     = get_nodes_block(node);
1445         ir_node  *new_block = be_transform_node(block);
1446         dbg_info *dbgi      = get_irn_dbg_info(node);
1447
1448         /* just produce a 0 */
1449         ir_mode *mode = get_irn_mode(node);
1450         if (mode_is_float(mode)) {
1451                 tarval *tv = get_mode_null(mode);
1452                 ir_node *node = new_bd_arm_fpaConst(dbgi, new_block, tv);
1453                 be_dep_on_frame(node);
1454                 return node;
1455         } else if (mode_needs_gp_reg(mode)) {
1456                 return create_const_graph_value(dbgi, new_block, 0);
1457         }
1458
1459         panic("Unexpected Unknown mode");
1460 }
1461
1462 /**
1463  * Change some phi modes
1464  */
1465 static ir_node *gen_Phi(ir_node *node)
1466 {
1467         const arch_register_req_t *req;
1468         ir_node  *block = be_transform_node(get_nodes_block(node));
1469         ir_graph *irg   = current_ir_graph;
1470         dbg_info *dbgi  = get_irn_dbg_info(node);
1471         ir_mode  *mode  = get_irn_mode(node);
1472         ir_node  *phi;
1473
1474         if (mode_needs_gp_reg(mode)) {
1475                 /* we shouldn't have any 64bit stuff around anymore */
1476                 assert(get_mode_size_bits(mode) <= 32);
1477                 /* all integer operations are on 32bit registers now */
1478                 mode = mode_Iu;
1479                 req  = arm_reg_classes[CLASS_arm_gp].class_req;
1480         } else {
1481                 req = arch_no_register_req;
1482         }
1483
1484         /* phi nodes allow loops, so we use the old arguments for now
1485          * and fix this later */
1486         phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node),
1487                           get_irn_in(node) + 1);
1488         copy_node_attr(node, phi);
1489         be_duplicate_deps(node, phi);
1490
1491         arch_set_out_register_req(phi, 0, req);
1492
1493         be_enqueue_preds(node);
1494
1495         return phi;
1496 }
1497
1498 /**
1499  * the BAD transformer.
1500  */
1501 static ir_node *bad_transform(ir_node *irn)
1502 {
1503         panic("ARM backend: Not implemented: %+F", irn);
1504 }
1505
1506 /**
1507  * Set a node emitter. Make it a bit more type safe.
1508  */
1509 static void set_transformer(ir_op *op, be_transform_func arm_transform_func)
1510 {
1511         op->ops.generic = (op_func)arm_transform_func;
1512 }
1513
1514 /**
1515  * Enters all transform functions into the generic pointer
1516  */
1517 static void arm_register_transformers(void)
1518 {
1519         /* first clear the generic function pointer for all ops */
1520         clear_irp_opcodes_generic_func();
1521
1522         set_transformer(op_Abs,          gen_Abs);
1523         set_transformer(op_Add,          gen_Add);
1524         set_transformer(op_And,          gen_And);
1525         set_transformer(op_be_AddSP,     gen_be_AddSP);
1526         set_transformer(op_be_Call,      gen_be_Call);
1527         set_transformer(op_be_Copy,      gen_be_Copy);
1528         set_transformer(op_be_FrameAddr, gen_be_FrameAddr);
1529         set_transformer(op_be_SubSP,     gen_be_SubSP);
1530         set_transformer(op_Cmp,          gen_Cmp);
1531         set_transformer(op_Cond,         gen_Cond);
1532         set_transformer(op_Const,        gen_Const);
1533         set_transformer(op_Conv,         gen_Conv);
1534         set_transformer(op_CopyB,        gen_CopyB);
1535         set_transformer(op_Eor,          gen_Eor);
1536         set_transformer(op_Jmp,          gen_Jmp);
1537         set_transformer(op_Load,         gen_Load);
1538         set_transformer(op_Minus,        gen_Minus);
1539         set_transformer(op_Mul,          gen_Mul);
1540         set_transformer(op_Not,          gen_Not);
1541         set_transformer(op_Or,           gen_Or);
1542         set_transformer(op_Phi,          gen_Phi);
1543         set_transformer(op_Proj,         gen_Proj);
1544         set_transformer(op_Quot,         gen_Quot);
1545         set_transformer(op_Rotl,         gen_Rotl);
1546         set_transformer(op_Shl,          gen_Shl);
1547         set_transformer(op_Shr,          gen_Shr);
1548         set_transformer(op_Shrs,         gen_Shrs);
1549         set_transformer(op_Store,        gen_Store);
1550         set_transformer(op_Sub,          gen_Sub);
1551         set_transformer(op_SymConst,     gen_SymConst);
1552         set_transformer(op_Unknown,      gen_Unknown);
1553
1554         set_transformer(op_ASM,       bad_transform);
1555         set_transformer(op_Builtin,   bad_transform);
1556         set_transformer(op_CallBegin, bad_transform);
1557         set_transformer(op_Cast,      bad_transform);
1558         set_transformer(op_Confirm,   bad_transform);
1559         set_transformer(op_DivMod,    bad_transform);
1560         set_transformer(op_EndExcept, bad_transform);
1561         set_transformer(op_EndReg,    bad_transform);
1562         set_transformer(op_Filter,    bad_transform);
1563         set_transformer(op_Free,      bad_transform);
1564         set_transformer(op_Id,        bad_transform);
1565         set_transformer(op_InstOf,    bad_transform);
1566         set_transformer(op_Mulh,      bad_transform);
1567         set_transformer(op_Mux,       bad_transform);
1568         set_transformer(op_Raise,     bad_transform);
1569         set_transformer(op_Sel,       bad_transform);
1570         set_transformer(op_Tuple,     bad_transform);
1571 }
1572
1573 /**
1574  * Pre-transform all unknown nodes.
1575  */
1576 static void arm_pretransform_node(void)
1577 {
1578         arm_code_gen_t *cg = env_cg;
1579
1580         cg->unknown_gp  = be_pre_transform_node(cg->unknown_gp);
1581         cg->unknown_fpa = be_pre_transform_node(cg->unknown_fpa);
1582 }
1583
1584 /**
1585  * Initialize fpa Immediate support.
1586  */
1587 static void arm_init_fpa_immediate(void)
1588 {
1589         /* 0, 1, 2, 3, 4, 5, 10, or 0.5. */
1590         fpa_imm[0][fpa_null]  = get_tarval_null(mode_F);
1591         fpa_imm[0][fpa_one]   = get_tarval_one(mode_F);
1592         fpa_imm[0][fpa_two]   = new_tarval_from_str("2", 1, mode_F);
1593         fpa_imm[0][fpa_three] = new_tarval_from_str("3", 1, mode_F);
1594         fpa_imm[0][fpa_four]  = new_tarval_from_str("4", 1, mode_F);
1595         fpa_imm[0][fpa_five]  = new_tarval_from_str("5", 1, mode_F);
1596         fpa_imm[0][fpa_ten]   = new_tarval_from_str("10", 2, mode_F);
1597         fpa_imm[0][fpa_half]  = new_tarval_from_str("0.5", 3, mode_F);
1598
1599         fpa_imm[1][fpa_null]  = get_tarval_null(mode_D);
1600         fpa_imm[1][fpa_one]   = get_tarval_one(mode_D);
1601         fpa_imm[1][fpa_two]   = new_tarval_from_str("2", 1, mode_D);
1602         fpa_imm[1][fpa_three] = new_tarval_from_str("3", 1, mode_D);
1603         fpa_imm[1][fpa_four]  = new_tarval_from_str("4", 1, mode_D);
1604         fpa_imm[1][fpa_five]  = new_tarval_from_str("5", 1, mode_D);
1605         fpa_imm[1][fpa_ten]   = new_tarval_from_str("10", 2, mode_D);
1606         fpa_imm[1][fpa_half]  = new_tarval_from_str("0.5", 3, mode_D);
1607
1608         fpa_imm[2][fpa_null]  = get_tarval_null(mode_E);
1609         fpa_imm[2][fpa_one]   = get_tarval_one(mode_E);
1610         fpa_imm[2][fpa_two]   = new_tarval_from_str("2", 1, mode_E);
1611         fpa_imm[2][fpa_three] = new_tarval_from_str("3", 1, mode_E);
1612         fpa_imm[2][fpa_four]  = new_tarval_from_str("4", 1, mode_E);
1613         fpa_imm[2][fpa_five]  = new_tarval_from_str("5", 1, mode_E);
1614         fpa_imm[2][fpa_ten]   = new_tarval_from_str("10", 2, mode_E);
1615         fpa_imm[2][fpa_half]  = new_tarval_from_str("0.5", 3, mode_E);
1616 }
1617
1618 /**
1619  * Transform a Firm graph into an ARM graph.
1620  */
1621 void arm_transform_graph(arm_code_gen_t *cg)
1622 {
1623         static int imm_initialized = 0;
1624
1625         if (! imm_initialized) {
1626                 arm_init_fpa_immediate();
1627                 imm_initialized = 1;
1628         }
1629         arm_register_transformers();
1630         env_cg = cg;
1631         be_transform_graph(cg->birg, arm_pretransform_node);
1632 }
1633
1634 void arm_init_transform(void)
1635 {
1636         FIRM_DBG_REGISTER(dbg, "firm.be.arm.transform");
1637 }