modernize TEMPLATE backend and simplify some backend APIs
[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 zero out upper bits.
124  *
125  * @param dbgi     debug info
126  * @param block    the basic block
127  * @param op       the original node
128  * param src_bits  number of lower bits that will remain
129  */
130 static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
131                                    int src_bits)
132 {
133         if (src_bits == 8) {
134                 return new_bd_arm_And_imm(dbgi, block, op, 0xFF, 0);
135         } else if (src_bits == 16) {
136                 ir_node *lshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, 16);
137                 ir_node *rshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift, ARM_SHF_LSR_IMM, 16);
138                 return rshift;
139         } else {
140                 panic("zero extension only supported for 8 and 16 bits");
141         }
142 }
143
144 /**
145  * Generate code for a sign extension.
146  */
147 static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
148                                    int src_bits)
149 {
150         int shift_width = 32 - src_bits;
151         ir_node *lshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, shift_width);
152         ir_node *rshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift_node, ARM_SHF_ASR_IMM, shift_width);
153         return rshift_node;
154 }
155
156 static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
157                               ir_mode *orig_mode)
158 {
159         int bits = get_mode_size_bits(orig_mode);
160         if (bits == 32)
161                 return op;
162
163         if (mode_is_signed(orig_mode)) {
164                 return gen_sign_extension(dbgi, block, op, bits);
165         } else {
166                 return gen_zero_extension(dbgi, block, op, bits);
167         }
168 }
169
170 /**
171  * returns true if it is assured, that the upper bits of a node are "clean"
172  * which means for a 16 or 8 bit value, that the upper bits in the register
173  * are 0 for unsigned and a copy of the last significant bit for signed
174  * numbers.
175  */
176 static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
177 {
178         (void) transformed_node;
179         (void) mode;
180         /* TODO */
181         return false;
182 }
183
184 /**
185  * Transforms a Conv node.
186  *
187  * @return The created ia32 Conv node
188  */
189 static ir_node *gen_Conv(ir_node *node)
190 {
191         ir_node  *block    = be_transform_node(get_nodes_block(node));
192         ir_node  *op       = get_Conv_op(node);
193         ir_node  *new_op   = be_transform_node(op);
194         ir_mode  *src_mode = get_irn_mode(op);
195         ir_mode  *dst_mode = get_irn_mode(node);
196         dbg_info *dbg      = get_irn_dbg_info(node);
197
198         if (src_mode == dst_mode)
199                 return new_op;
200
201         if (mode_is_float(src_mode) || mode_is_float(dst_mode)) {
202                 env_cg->have_fp_insn = 1;
203
204                 if (USE_FPA(env_cg->isa)) {
205                         if (mode_is_float(src_mode)) {
206                                 if (mode_is_float(dst_mode)) {
207                                         /* from float to float */
208                                         return new_bd_arm_fpaMvf(dbg, block, new_op, dst_mode);
209                                 }
210                                 else {
211                                         /* from float to int */
212                                         return new_bd_arm_fpaFix(dbg, block, new_op, dst_mode);
213                                 }
214                         }
215                         else {
216                                 /* from int to float */
217                                 return new_bd_arm_fpaFlt(dbg, block, new_op, dst_mode);
218                         }
219                 } else if (USE_VFP(env_cg->isa)) {
220                         panic("VFP not supported yet");
221                 } else {
222                         panic("Softfloat not supported yet");
223                 }
224         } else { /* complete in gp registers */
225                 int src_bits = get_mode_size_bits(src_mode);
226                 int dst_bits = get_mode_size_bits(dst_mode);
227                 int min_bits;
228                 ir_mode *min_mode;
229
230                 if (src_bits == dst_bits) {
231                         /* kill unneccessary conv */
232                         return new_op;
233                 }
234
235                 if (src_bits < dst_bits) {
236                         min_bits = src_bits;
237                         min_mode = src_mode;
238                 } else {
239                         min_bits = dst_bits;
240                         min_mode = dst_mode;
241                 }
242
243                 if (upper_bits_clean(new_op, min_mode)) {
244                         return new_op;
245                 }
246
247                 if (mode_is_signed(min_mode)) {
248                         return gen_sign_extension(dbg, block, new_op, min_bits);
249                 } else {
250                         return gen_zero_extension(dbg, block, new_op, min_bits);
251                 }
252         }
253 }
254
255 typedef struct {
256         unsigned char  imm_8;
257         unsigned char  rot;
258 } arm_immediate_t;
259
260 static bool try_encode_as_immediate(const ir_node *node, arm_immediate_t *res)
261 {
262         unsigned val, low_pos, high_pos;
263
264         if (!is_Const(node))
265                 return false;
266
267         val = get_tarval_long(get_Const_tarval(node));
268
269         if (val == 0) {
270                 res->imm_8 = 0;
271                 res->rot   = 0;
272                 return true;
273         }
274         if (val <= 0xff) {
275                 res->imm_8 = val;
276                 res->rot   = 0;
277                 return true;
278         }
279         /* arm allows to use to rotate an 8bit immediate value by a multiple of 2
280            (= 0, 2, 4, 6, ...).
281            So we determine the smallest even position with a bit set
282            and the highest even position with no bit set anymore.
283            If the difference between these 2 is <= 8, then we can encode the value
284            as immediate.
285          */
286         low_pos  = ntz(val) & ~1u;
287         high_pos = (32-nlz(val)+1) & ~1u;
288
289         if (high_pos - low_pos <= 8) {
290                 res->imm_8 = val >> low_pos;
291                 res->rot   = 32 - low_pos;
292                 return true;
293         }
294
295         if (high_pos > 24) {
296                 res->rot = 34 - high_pos;
297                 val      = val >> (32-res->rot) | val << (res->rot);
298                 if (val <= 0xff) {
299                         res->imm_8 = val;
300                         return true;
301                 }
302         }
303
304         return false;
305 }
306
307 static int is_downconv(const ir_node *node)
308 {
309         ir_mode *src_mode;
310         ir_mode *dest_mode;
311
312         if (!is_Conv(node))
313                 return 0;
314
315         /* we only want to skip the conv when we're the only user
316          * (not optimal but for now...)
317          */
318         if (get_irn_n_edges(node) > 1)
319                 return 0;
320
321         src_mode  = get_irn_mode(get_Conv_op(node));
322         dest_mode = get_irn_mode(node);
323         return
324                 mode_needs_gp_reg(src_mode)  &&
325                 mode_needs_gp_reg(dest_mode) &&
326                 get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
327 }
328
329 static ir_node *arm_skip_downconv(ir_node *node)
330 {
331         while (is_downconv(node))
332                 node = get_Conv_op(node);
333         return node;
334 }
335
336 typedef enum {
337         MATCH_NONE         = 0,
338         MATCH_COMMUTATIVE  = 1 << 0,
339         MATCH_SIZE_NEUTRAL = 1 << 1,
340 } match_flags_t;
341
342 typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2);
343 typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, unsigned char imm8, unsigned char imm_rot);
344
345 static ir_node *gen_int_binop(ir_node *node, match_flags_t flags,
346                 new_binop_reg_func new_reg, new_binop_imm_func new_imm)
347 {
348         ir_node  *block   = be_transform_node(get_nodes_block(node));
349         ir_node  *op1     = get_binop_left(node);
350         ir_node  *new_op1;
351         ir_node  *op2     = get_binop_right(node);
352         ir_node  *new_op2;
353         dbg_info *dbgi    = get_irn_dbg_info(node);
354         arm_immediate_t imm;
355
356         if (flags & MATCH_SIZE_NEUTRAL) {
357                 op1 = arm_skip_downconv(op1);
358                 op2 = arm_skip_downconv(op2);
359         } else {
360                 assert(get_mode_size_bits(get_irn_mode(node)) == 32);
361         }
362
363         if (try_encode_as_immediate(op2, &imm)) {
364                 ir_node *new_op1 = be_transform_node(op1);
365                 return new_imm(dbgi, block, new_op1, imm.imm_8, imm.rot);
366         }
367         new_op2 = be_transform_node(op2);
368     if ((flags & MATCH_COMMUTATIVE) && try_encode_as_immediate(op1, &imm)) {
369                 return new_imm(dbgi, block, new_op2, imm.imm_8, imm.rot);
370         }
371         new_op1 = be_transform_node(op1);
372
373         return new_reg(dbgi, block, new_op1, new_op2);
374 }
375
376 /**
377  * Creates an ARM Add.
378  *
379  * @return the created arm Add node
380  */
381 static ir_node *gen_Add(ir_node *node)
382 {
383         ir_mode  *mode    = get_irn_mode(node);
384
385         if (mode_is_float(mode)) {
386                 ir_node  *block   = be_transform_node(get_nodes_block(node));
387                 ir_node  *op1     = get_Add_left(node);
388                 ir_node  *op2     = get_Add_right(node);
389                 dbg_info *dbgi    = get_irn_dbg_info(node);
390                 ir_node  *new_op1 = be_transform_node(op1);
391                 ir_node  *new_op2 = be_transform_node(op2);
392                 env_cg->have_fp_insn = 1;
393                 if (USE_FPA(env_cg->isa)) {
394 #if 0
395                         if (is_arm_fpaMvf_i(new_op1))
396                                 return new_bd_arm_fpaAdf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
397                         if (is_arm_fpaMvf_i(new_op2))
398                                 return new_bd_arm_fpaAdf_i(dbgi, block, new_op1, mode, get_arm_imm_value(new_op2));
399 #endif
400                         return new_bd_arm_fpaAdf(dbgi, block, new_op1, new_op2, mode);
401                 } else if (USE_VFP(env_cg->isa)) {
402                         assert(mode != mode_E && "IEEE Extended FP not supported");
403                         panic("VFP not supported yet");
404                 }
405                 else {
406                         panic("Softfloat not supported yet");
407                 }
408         } else {
409 #if 0
410                 /* check for MLA */
411                 if (is_arm_Mul(new_op1) && get_irn_n_edges(op1) == 1) {
412                         new_op3 = new_op2;
413                         new_op2 = get_irn_n(new_op1, 1);
414                         new_op1 = get_irn_n(new_op1, 0);
415
416                         return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
417                 }
418                 if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
419                         new_op3 = new_op1;
420                         new_op1 = get_irn_n(new_op2, 0);
421                         new_op2 = get_irn_n(new_op2, 1);
422
423                         return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
424                 }
425 #endif
426
427                 return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
428                                 new_bd_arm_Add_reg, new_bd_arm_Add_imm);
429         }
430 }
431
432 /**
433  * Creates an ARM Mul.
434  *
435  * @return the created arm Mul node
436  */
437 static ir_node *gen_Mul(ir_node *node)
438 {
439         ir_node  *block   = be_transform_node(get_nodes_block(node));
440         ir_node  *op1     = get_Mul_left(node);
441         ir_node  *new_op1 = be_transform_node(op1);
442         ir_node  *op2     = get_Mul_right(node);
443         ir_node  *new_op2 = be_transform_node(op2);
444         ir_mode  *mode    = get_irn_mode(node);
445         dbg_info *dbg     = get_irn_dbg_info(node);
446
447         if (mode_is_float(mode)) {
448                 env_cg->have_fp_insn = 1;
449                 if (USE_FPA(env_cg->isa)) {
450 #if 0
451                         if (is_arm_Mov_i(new_op1))
452                                 return new_bd_arm_fpaMuf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
453                         if (is_arm_Mov_i(new_op2))
454                                 return new_bd_arm_fpaMuf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
455 #endif
456                         return new_bd_arm_fpaMuf(dbg, block, new_op1, new_op2, mode);
457                 }
458                 else if (USE_VFP(env_cg->isa)) {
459                         assert(mode != mode_E && "IEEE Extended FP not supported");
460                         panic("VFP not supported yet");
461                 }
462                 else {
463                         panic("Softfloat not supported yet");
464                 }
465         }
466         assert(mode_is_data(mode));
467         return new_bd_arm_Mul(dbg, block, new_op1, new_op2);
468 }
469
470 /**
471  * Creates an ARM floating point Div.
472  *
473  * @param env   The transformation environment
474  * @return the created arm fDiv node
475  */
476 static ir_node *gen_Quot(ir_node *node)
477 {
478         ir_node  *block   = be_transform_node(get_nodes_block(node));
479         ir_node  *op1     = get_Quot_left(node);
480         ir_node  *new_op1 = be_transform_node(op1);
481         ir_node  *op2     = get_Quot_right(node);
482         ir_node  *new_op2 = be_transform_node(op2);
483         ir_mode  *mode    = get_irn_mode(node);
484         dbg_info *dbg     = get_irn_dbg_info(node);
485
486         assert(mode != mode_E && "IEEE Extended FP not supported");
487
488         env_cg->have_fp_insn = 1;
489         if (USE_FPA(env_cg->isa)) {
490 #if 0
491                 if (is_arm_Mov_i(new_op1))
492                         return new_bd_arm_fpaRdf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
493                 if (is_arm_Mov_i(new_op2))
494                         return new_bd_arm_fpaDvf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
495 #endif
496                 return new_bd_arm_fpaDvf(dbg, block, new_op1, new_op2, mode);
497         } else if (USE_VFP(env_cg->isa)) {
498                 assert(mode != mode_E && "IEEE Extended FP not supported");
499                 panic("VFP not supported yet");
500         }
501         else {
502                 panic("Softfloat not supported yet");
503         }
504 }
505
506 /**
507  * Creates an ARM And.
508  *
509  * @return the created arm And node
510  */
511 static ir_node *gen_And(ir_node *node)
512 {
513         return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
514                         new_bd_arm_And_reg, new_bd_arm_And_imm);
515 }
516
517 /**
518  * Creates an ARM Orr.
519  *
520  * @param env   The transformation environment
521  * @return the created arm Or node
522  */
523 static ir_node *gen_Or(ir_node *node)
524 {
525         return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
526                         new_bd_arm_Or_reg, new_bd_arm_Or_imm);
527 }
528
529 /**
530  * Creates an ARM Eor.
531  *
532  * @return the created arm Eor node
533  */
534 static ir_node *gen_Eor(ir_node *node)
535 {
536         return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
537                         new_bd_arm_Eor_reg, new_bd_arm_Eor_imm);
538 }
539
540 /**
541  * Creates an ARM Sub.
542  *
543  * @return the created arm Sub node
544  */
545 static ir_node *gen_Sub(ir_node *node)
546 {
547         ir_node  *block   = be_transform_node(get_nodes_block(node));
548         ir_node  *op1     = get_Sub_left(node);
549         ir_node  *new_op1 = be_transform_node(op1);
550         ir_node  *op2     = get_Sub_right(node);
551         ir_node  *new_op2 = be_transform_node(op2);
552         ir_mode  *mode    = get_irn_mode(node);
553         dbg_info *dbgi    = get_irn_dbg_info(node);
554
555         if (mode_is_float(mode)) {
556                 env_cg->have_fp_insn = 1;
557                 if (USE_FPA(env_cg->isa)) {
558 #if 0
559                         if (is_arm_Mov_i(new_op1))
560                                 return new_bd_arm_fpaRsf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
561                         if (is_arm_Mov_i(new_op2))
562                                 return new_bd_arm_fpaSuf_i(dbgi, block, new_op1, mode, get_arm_imm_value(new_op2));
563 #endif
564                         return new_bd_arm_fpaSuf(dbgi, block, new_op1, new_op2, mode);
565                 } else if (USE_VFP(env_cg->isa)) {
566                         assert(mode != mode_E && "IEEE Extended FP not supported");
567                         panic("VFP not supported yet");
568                 } else {
569                         panic("Softfloat not supported yet");
570                 }
571         } else {
572                 return gen_int_binop(node, MATCH_SIZE_NEUTRAL,
573                                 new_bd_arm_Sub_reg, new_bd_arm_Sub_imm);
574         }
575 }
576
577 static ir_node *make_shift(ir_node *node, match_flags_t flags,
578                 arm_shift_modifier shift_modifier)
579 {
580         ir_node  *block   = be_transform_node(get_nodes_block(node));
581         ir_node  *op1     = get_binop_left(node);
582         ir_node  *op2     = get_binop_right(node);
583         dbg_info *dbgi    = get_irn_dbg_info(node);
584         ir_node  *new_op1;
585         ir_node  *new_op2;
586
587         if (flags & MATCH_SIZE_NEUTRAL) {
588                 op1 = arm_skip_downconv(op1);
589                 op2 = arm_skip_downconv(op2);
590         }
591         new_op1 = be_transform_node(op1);
592         new_op2 = be_transform_node(op2);
593         return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2, shift_modifier);
594 }
595
596 /**
597  * Creates an ARM Shl.
598  *
599  * @return the created ARM Shl node
600  */
601 static ir_node *gen_Shl(ir_node *node)
602 {
603         return make_shift(node, MATCH_SIZE_NEUTRAL, ARM_SHF_LSL_REG);
604 }
605
606 /**
607  * Creates an ARM Shr.
608  *
609  * @return the created ARM Shr node
610  */
611 static ir_node *gen_Shr(ir_node *node)
612 {
613         return make_shift(node, MATCH_NONE, ARM_SHF_LSR_REG);
614 }
615
616 /**
617  * Creates an ARM Shrs.
618  *
619  * @return the created ARM Shrs node
620  */
621 static ir_node *gen_Shrs(ir_node *node)
622 {
623         return make_shift(node, MATCH_NONE, ARM_SHF_ASR_REG);
624 }
625
626 /**
627  * Creates an ARM Ror.
628  *
629  * @return the created ARM Ror node
630  */
631 static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2)
632 {
633         ir_node  *block   = be_transform_node(get_nodes_block(node));
634         ir_node  *new_op1 = be_transform_node(op1);
635         dbg_info *dbgi    = get_irn_dbg_info(node);
636         ir_node  *new_op2 = be_transform_node(op2);
637
638         return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
639                                             ARM_SHF_ROR_REG);
640 }
641
642 /**
643  * Creates an ARM Rol.
644  *
645  * @return the created ARM Rol node
646  *
647  * Note: there is no Rol on arm, we have to use Ror
648  */
649 static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2)
650 {
651         ir_node  *block   = be_transform_node(get_nodes_block(node));
652         ir_node  *new_op1 = be_transform_node(op1);
653         dbg_info *dbgi    = get_irn_dbg_info(node);
654         ir_node  *new_op2 = be_transform_node(op2);
655
656         new_op2 = new_bd_arm_Rsb_imm(dbgi, block, new_op2, 32, 0);
657         return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
658                                             ARM_SHF_ROR_REG);
659 }
660
661 /**
662  * Creates an ARM ROR from a Firm Rotl.
663  *
664  * @return the created ARM Ror node
665  */
666 static ir_node *gen_Rotl(ir_node *node)
667 {
668         ir_node *rotate = NULL;
669         ir_node *op1    = get_Rotl_left(node);
670         ir_node *op2    = get_Rotl_right(node);
671
672         /* Firm has only RotL, so we are looking for a right (op2)
673            operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
674            that means we can create a RotR. */
675
676         if (is_Add(op2)) {
677                 ir_node *right = get_Add_right(op2);
678                 if (is_Const(right)) {
679                         tarval  *tv   = get_Const_tarval(right);
680                         ir_mode *mode = get_irn_mode(node);
681                         long     bits = get_mode_size_bits(mode);
682                         ir_node *left = get_Add_left(op2);
683
684                         if (is_Minus(left) &&
685                             tarval_is_long(tv)          &&
686                             get_tarval_long(tv) == bits &&
687                             bits                == 32)
688                                 rotate = gen_Ror(node, op1, get_Minus_op(left));
689                 }
690         } else if (is_Sub(op2)) {
691                 ir_node *left = get_Sub_left(op2);
692                 if (is_Const(left)) {
693                         tarval  *tv   = get_Const_tarval(left);
694                         ir_mode *mode = get_irn_mode(node);
695                         long     bits = get_mode_size_bits(mode);
696                         ir_node *right = get_Sub_right(op2);
697
698                         if (tarval_is_long(tv)          &&
699                             get_tarval_long(tv) == bits &&
700                             bits                == 32)
701                                 rotate = gen_Ror(node, op1, right);
702                 }
703         } else if (is_Const(op2)) {
704                 tarval  *tv   = get_Const_tarval(op2);
705                 ir_mode *mode = get_irn_mode(node);
706                 long     bits = get_mode_size_bits(mode);
707
708                 if (tarval_is_long(tv) && bits == 32) {
709                         ir_node  *block   = be_transform_node(get_nodes_block(node));
710                         ir_node  *new_op1 = be_transform_node(op1);
711                         dbg_info *dbgi    = get_irn_dbg_info(node);
712
713                         bits = (bits - get_tarval_long(tv)) & 31;
714                         rotate = new_bd_arm_Mov_reg_shift_imm(dbgi, block, new_op1, ARM_SHF_ROR_IMM, bits);
715                 }
716         }
717
718         if (rotate == NULL) {
719                 rotate = gen_Rol(node, op1, op2);
720         }
721
722         return rotate;
723 }
724
725 /**
726  * Transforms a Not node.
727  *
728  * @return the created ARM Not node
729  */
730 static ir_node *gen_Not(ir_node *node)
731 {
732         ir_node  *block   = be_transform_node(get_nodes_block(node));
733         ir_node  *op      = get_Not_op(node);
734         ir_node  *new_op  = be_transform_node(op);
735         dbg_info *dbgi    = get_irn_dbg_info(node);
736
737         /* TODO: we could do alot more here with all the Mvn variations */
738
739         return new_bd_arm_Mvn_reg(dbgi, block, new_op);
740 }
741
742 /**
743  * Transforms an Abs node.
744  *
745  * @param env   The transformation environment
746  * @return the created ARM Abs node
747  */
748 static ir_node *gen_Abs(ir_node *node)
749 {
750         ir_node  *block   = be_transform_node(get_nodes_block(node));
751         ir_node  *op      = get_Abs_op(node);
752         ir_node  *new_op  = be_transform_node(op);
753         dbg_info *dbgi    = get_irn_dbg_info(node);
754         ir_mode  *mode    = get_irn_mode(node);
755
756         if (mode_is_float(mode)) {
757                 env_cg->have_fp_insn = 1;
758                 if (USE_FPA(env_cg->isa))
759                         return new_bd_arm_fpaAbs(dbgi, block, new_op, mode);
760                 else if (USE_VFP(env_cg->isa)) {
761                         assert(mode != mode_E && "IEEE Extended FP not supported");
762                         panic("VFP not supported yet");
763                 }
764                 else {
765                         panic("Softfloat not supported yet");
766                 }
767         }
768         assert(mode_is_data(mode));
769         return new_bd_arm_Abs(dbgi, block, new_op);
770 }
771
772 /**
773  * Transforms a Minus node.
774  *
775  * @return the created ARM Minus node
776  */
777 static ir_node *gen_Minus(ir_node *node)
778 {
779         ir_node  *block   = be_transform_node(get_nodes_block(node));
780         ir_node  *op      = get_Minus_op(node);
781         ir_node  *new_op  = be_transform_node(op);
782         dbg_info *dbgi    = get_irn_dbg_info(node);
783         ir_mode  *mode    = get_irn_mode(node);
784
785         if (mode_is_float(mode)) {
786                 env_cg->have_fp_insn = 1;
787                 if (USE_FPA(env_cg->isa))
788                         return new_bd_arm_fpaMvf(dbgi, block, op, mode);
789                 else if (USE_VFP(env_cg->isa)) {
790                         assert(mode != mode_E && "IEEE Extended FP not supported");
791                         panic("VFP not supported yet");
792                 }
793                 else {
794                         panic("Softfloat not supported yet");
795                 }
796         }
797         assert(mode_is_data(mode));
798         return new_bd_arm_Rsb_imm(dbgi, block, new_op, 0, 0);
799 }
800
801 /**
802  * Transforms a Load.
803  *
804  * @return the created ARM Load node
805  */
806 static ir_node *gen_Load(ir_node *node)
807 {
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(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_is_negative(tv)) {
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 {
1063         ir_node  *block = be_transform_node(get_nodes_block(node));
1064         ir_mode *mode = get_irn_mode(node);
1065         dbg_info *dbg = get_irn_dbg_info(node);
1066
1067         if (mode_is_float(mode)) {
1068                 env_cg->have_fp_insn = 1;
1069                 if (USE_FPA(env_cg->isa)) {
1070                         tarval *tv = get_Const_tarval(node);
1071 #if 0
1072                         int imm = is_fpa_immediate(tv);
1073
1074                         if (imm != fpa_max) {
1075                                 if (imm > 0)
1076                                         node = new_bd_arm_fpaMvf_i(dbg, block, mode, imm);
1077                                 else
1078                                         node = new_bd_arm_fpaMnf_i(dbg, block, mode, -imm);
1079                         } else {
1080 #endif
1081                         {
1082                                 node = new_bd_arm_fpaConst(dbg, block, tv);
1083                         }
1084                         be_dep_on_frame(node);
1085                         return node;
1086                 }
1087                 else if (USE_VFP(env_cg->isa)) {
1088                         assert(mode != mode_E && "IEEE Extended FP not supported");
1089                         panic("VFP not supported yet");
1090                 }
1091                 else {
1092                         panic("Softfloat not supported yet");
1093                 }
1094         }
1095         return create_const_graph(node, block);
1096 }
1097
1098 /**
1099  * Transforms a SymConst node.
1100  *
1101  * @return The transformed ARM node.
1102  */
1103 static ir_node *gen_SymConst(ir_node *node)
1104 {
1105         ir_node   *block  = be_transform_node(get_nodes_block(node));
1106         ir_entity *entity = get_SymConst_entity(node);
1107         dbg_info  *dbgi   = get_irn_dbg_info(node);
1108         ir_node   *new_node;
1109
1110         new_node = new_bd_arm_SymConst(dbgi, block, entity);
1111         be_dep_on_frame(new_node);
1112         return new_node;
1113 }
1114
1115 /**
1116  * Transforms a CopyB node.
1117  *
1118  * @return The transformed ARM node.
1119  */
1120 static ir_node *gen_CopyB(ir_node *node)
1121 {
1122         ir_node  *block    = be_transform_node(get_nodes_block(node));
1123         ir_node  *src      = get_CopyB_src(node);
1124         ir_node  *new_src  = be_transform_node(src);
1125         ir_node  *dst      = get_CopyB_dst(node);
1126         ir_node  *new_dst  = be_transform_node(dst);
1127         ir_node  *mem      = get_CopyB_mem(node);
1128         ir_node  *new_mem  = be_transform_node(mem);
1129         dbg_info *dbg      = get_irn_dbg_info(node);
1130         int      size      = get_type_size_bytes(get_CopyB_type(node));
1131         ir_node  *src_copy;
1132         ir_node  *dst_copy;
1133
1134         src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], block, new_src);
1135         dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], block, new_dst);
1136
1137         return new_bd_arm_CopyB(dbg, block, dst_copy, src_copy,
1138                         new_bd_arm_EmptyReg(dbg, block),
1139                         new_bd_arm_EmptyReg(dbg, block),
1140                         new_bd_arm_EmptyReg(dbg, block),
1141                         new_mem, size);
1142 }
1143
1144 /**
1145  * Transforms a FrameAddr into an ARM Add.
1146  */
1147 static ir_node *gen_be_FrameAddr(ir_node *node)
1148 {
1149         ir_node   *block  = be_transform_node(get_nodes_block(node));
1150         ir_entity *ent    = be_get_frame_entity(node);
1151         ir_node   *fp     = be_get_FrameAddr_frame(node);
1152         ir_node   *new_fp = be_transform_node(fp);
1153         dbg_info  *dbgi   = get_irn_dbg_info(node);
1154         ir_node   *new_node;
1155
1156         new_node = new_bd_arm_FrameAddr(dbgi, block, new_fp, ent);
1157         return new_node;
1158 }
1159
1160 /**
1161  * Transform a be_AddSP into an arm_AddSP. Eat up const sizes.
1162  */
1163 static ir_node *gen_be_AddSP(ir_node *node)
1164 {
1165         ir_node  *block  = be_transform_node(get_nodes_block(node));
1166         ir_node  *sz     = get_irn_n(node, be_pos_AddSP_size);
1167         ir_node  *new_sz = be_transform_node(sz);
1168         ir_node  *sp     = get_irn_n(node, be_pos_AddSP_old_sp);
1169         ir_node  *new_sp = be_transform_node(sp);
1170         dbg_info *dbgi   = get_irn_dbg_info(node);
1171         ir_node  *nomem  = new_NoMem();
1172         ir_node  *new_op;
1173
1174         /* ARM stack grows in reverse direction, make a SubSPandCopy */
1175         new_op = new_bd_arm_SubSPandCopy(dbgi, block, new_sp, new_sz, nomem);
1176
1177         return new_op;
1178 }
1179
1180 /**
1181  * Transform a be_SubSP into an arm_SubSP. Eat up const sizes.
1182  */
1183 static ir_node *gen_be_SubSP(ir_node *node)
1184 {
1185         ir_node  *block  = be_transform_node(get_nodes_block(node));
1186         ir_node  *sz     = get_irn_n(node, be_pos_SubSP_size);
1187         ir_node  *new_sz = be_transform_node(sz);
1188         ir_node  *sp     = get_irn_n(node, be_pos_SubSP_old_sp);
1189         ir_node  *new_sp = be_transform_node(sp);
1190         dbg_info *dbgi   = get_irn_dbg_info(node);
1191         ir_node  *nomem  = new_NoMem();
1192         ir_node  *new_op;
1193
1194         /* ARM stack grows in reverse direction, make an AddSP */
1195         new_op = new_bd_arm_AddSP(dbgi, block, new_sp, new_sz, nomem);
1196
1197         return new_op;
1198 }
1199
1200 /**
1201  * Transform a be_Copy.
1202  */
1203 static ir_node *gen_be_Copy(ir_node *node)
1204 {
1205         ir_node *result = be_duplicate_node(node);
1206         ir_mode *mode   = get_irn_mode(result);
1207
1208         if (mode_needs_gp_reg(mode)) {
1209                 set_irn_mode(node, mode_Iu);
1210         }
1211
1212         return result;
1213 }
1214
1215 /**
1216  * Transform a Proj from a Load.
1217  */
1218 static ir_node *gen_Proj_Load(ir_node *node)
1219 {
1220         ir_node  *load     = get_Proj_pred(node);
1221         ir_node  *new_load = be_transform_node(load);
1222         dbg_info *dbgi     = get_irn_dbg_info(node);
1223         long     proj      = get_Proj_proj(node);
1224
1225         /* renumber the proj */
1226         switch (get_arm_irn_opcode(new_load)) {
1227         case iro_arm_Ldr:
1228                 /* handle all gp loads equal: they have the same proj numbers. */
1229                 if (proj == pn_Load_res) {
1230                         return new_rd_Proj(dbgi, new_load, mode_Iu, pn_arm_Ldr_res);
1231                 } else if (proj == pn_Load_M) {
1232                         return new_rd_Proj(dbgi, new_load, mode_M, pn_arm_Ldr_M);
1233                 }
1234                 break;
1235         case iro_arm_fpaLdf:
1236                 if (proj == pn_Load_res) {
1237                         ir_mode *mode = get_Load_mode(load);
1238                         return new_rd_Proj(dbgi, new_load, mode, pn_arm_fpaLdf_res);
1239                 } else if (proj == pn_Load_M) {
1240                         return new_rd_Proj(dbgi, new_load, mode_M, pn_arm_fpaLdf_M);
1241                 }
1242                 break;
1243         default:
1244                 break;
1245         }
1246         panic("Unsupported Proj from Load");
1247 }
1248
1249 /**
1250  * Transform and renumber the Projs from a CopyB.
1251  */
1252 static ir_node *gen_Proj_CopyB(ir_node *node)
1253 {
1254         ir_node  *pred     = get_Proj_pred(node);
1255         ir_node  *new_pred = be_transform_node(pred);
1256         dbg_info *dbgi     = get_irn_dbg_info(node);
1257         long     proj      = get_Proj_proj(node);
1258
1259         switch (proj) {
1260         case pn_CopyB_M_regular:
1261                 if (is_arm_CopyB(new_pred)) {
1262                         return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_CopyB_M);
1263                 }
1264                 break;
1265         default:
1266                 break;
1267         }
1268         panic("Unsupported Proj from CopyB");
1269 }
1270
1271 /**
1272  * Transform and renumber the Projs from a Quot.
1273  */
1274 static ir_node *gen_Proj_Quot(ir_node *node)
1275 {
1276         ir_node  *pred     = get_Proj_pred(node);
1277         ir_node  *new_pred = be_transform_node(pred);
1278         dbg_info *dbgi     = get_irn_dbg_info(node);
1279         ir_mode  *mode     = get_irn_mode(node);
1280         long     proj      = get_Proj_proj(node);
1281
1282         switch (proj) {
1283         case pn_Quot_M:
1284                 if (is_arm_fpaDvf(new_pred)) {
1285                         return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_fpaDvf_M);
1286                 } else if (is_arm_fpaRdf(new_pred)) {
1287                         return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_fpaRdf_M);
1288                 } else if (is_arm_fpaFdv(new_pred)) {
1289                         return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_fpaFdv_M);
1290                 } else if (is_arm_fpaFrd(new_pred)) {
1291                         return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_fpaFrd_M);
1292                 }
1293                 break;
1294         case pn_Quot_res:
1295                 if (is_arm_fpaDvf(new_pred)) {
1296                         return new_rd_Proj(dbgi, new_pred, mode, pn_arm_fpaDvf_res);
1297                 } else if (is_arm_fpaRdf(new_pred)) {
1298                         return new_rd_Proj(dbgi, new_pred, mode, pn_arm_fpaRdf_res);
1299                 } else if (is_arm_fpaFdv(new_pred)) {
1300                         return new_rd_Proj(dbgi, new_pred, mode, pn_arm_fpaFdv_res);
1301                 } else if (is_arm_fpaFrd(new_pred)) {
1302                         return new_rd_Proj(dbgi, new_pred, mode, pn_arm_fpaFrd_res);
1303                 }
1304                 break;
1305         default:
1306                 break;
1307         }
1308         panic("Unsupported Proj from Quot");
1309 }
1310
1311 /**
1312  * Transform the Projs of a be_AddSP.
1313  */
1314 static ir_node *gen_Proj_be_AddSP(ir_node *node)
1315 {
1316         ir_node  *pred     = get_Proj_pred(node);
1317         ir_node  *new_pred = be_transform_node(pred);
1318         dbg_info *dbgi     = get_irn_dbg_info(node);
1319         long     proj      = get_Proj_proj(node);
1320
1321         if (proj == pn_be_AddSP_sp) {
1322                 ir_node *res = new_rd_Proj(dbgi, new_pred, mode_Iu,
1323                                            pn_arm_SubSPandCopy_stack);
1324                 arch_set_irn_register(res, &arm_gp_regs[REG_SP]);
1325                 return res;
1326         } else if (proj == pn_be_AddSP_res) {
1327                 return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_arm_SubSPandCopy_addr);
1328         } else if (proj == pn_be_AddSP_M) {
1329                 return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_SubSPandCopy_M);
1330         }
1331         panic("Unsupported Proj from AddSP");
1332 }
1333
1334 /**
1335  * Transform the Projs of a be_SubSP.
1336  */
1337 static ir_node *gen_Proj_be_SubSP(ir_node *node)
1338 {
1339         ir_node  *pred     = get_Proj_pred(node);
1340         ir_node  *new_pred = be_transform_node(pred);
1341         dbg_info *dbgi     = get_irn_dbg_info(node);
1342         long     proj      = get_Proj_proj(node);
1343
1344         if (proj == pn_be_SubSP_sp) {
1345                 ir_node *res = new_rd_Proj(dbgi, new_pred, mode_Iu,
1346                                            pn_arm_AddSP_stack);
1347                 arch_set_irn_register(res, &arm_gp_regs[REG_SP]);
1348                 return res;
1349         } else if (proj == pn_be_SubSP_M) {
1350                 return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_AddSP_M);
1351         }
1352         panic("Unsupported Proj from SubSP");
1353 }
1354
1355 /**
1356  * Transform the Projs from a Cmp.
1357  */
1358 static ir_node *gen_Proj_Cmp(ir_node *node)
1359 {
1360         (void) node;
1361         panic("Mux NYI");
1362 }
1363
1364
1365 /**
1366  * Transform the Thread Local Storage Proj.
1367  */
1368 static ir_node *gen_Proj_tls(ir_node *node)
1369 {
1370         ir_node  *block = be_transform_node(get_nodes_block(node));
1371         dbg_info *dbgi  = NULL;
1372
1373         return new_bd_arm_LdTls(dbgi, block, mode_Iu);
1374 }
1375
1376 /**
1377  * Transform a Proj node.
1378  */
1379 static ir_node *gen_Proj(ir_node *node)
1380 {
1381         ir_graph *irg  = current_ir_graph;
1382         dbg_info *dbgi = get_irn_dbg_info(node);
1383         ir_node  *pred = get_Proj_pred(node);
1384         long     proj  = get_Proj_proj(node);
1385
1386         if (is_Store(pred)) {
1387                 if (proj == pn_Store_M) {
1388                         return be_transform_node(pred);
1389                 } else {
1390                         panic("Unsupported Proj from Store");
1391                 }
1392         } else if (is_Load(pred)) {
1393                 return gen_Proj_Load(node);
1394         } else if (is_CopyB(pred)) {
1395                 return gen_Proj_CopyB(node);
1396         } else if (is_Quot(pred)) {
1397                 return gen_Proj_Quot(node);
1398         } else if (be_is_SubSP(pred)) {
1399                 return gen_Proj_be_SubSP(node);
1400         } else if (be_is_AddSP(pred)) {
1401                 return gen_Proj_be_AddSP(node);
1402         } else if (is_Cmp(pred)) {
1403                 return gen_Proj_Cmp(node);
1404         } else if (is_Start(pred)) {
1405                 if (proj == pn_Start_X_initial_exec) {
1406                         ir_node *block = get_nodes_block(pred);
1407                         ir_node *jump;
1408
1409                         /* we exchange the ProjX with a jump */
1410                         block = be_transform_node(block);
1411                         jump  = new_rd_Jmp(dbgi, block);
1412                         return jump;
1413                 }
1414                 if (node == get_irg_anchor(irg, anchor_tls)) {
1415                         return gen_Proj_tls(node);
1416                 }
1417         } else {
1418                 ir_node *new_pred = be_transform_node(pred);
1419                 ir_mode *mode     = get_irn_mode(node);
1420                 if (mode_needs_gp_reg(mode)) {
1421                         ir_node *new_proj = new_r_Proj(new_pred, mode_Iu,
1422                                                        get_Proj_proj(node));
1423                         new_proj->node_nr = node->node_nr;
1424                         return new_proj;
1425                 }
1426         }
1427
1428         return be_duplicate_node(node);
1429 }
1430
1431 typedef ir_node *(*create_const_node_func)(dbg_info *db, ir_node *block);
1432
1433 static inline ir_node *create_const(ir_node **place,
1434                                     create_const_node_func func,
1435                                     const arch_register_t* reg)
1436 {
1437         ir_node *block, *res;
1438
1439         if (*place != NULL)
1440                 return *place;
1441
1442         block = get_irg_start_block(env_cg->irg);
1443         res = func(NULL, block);
1444         arch_set_irn_register(res, reg);
1445         *place = res;
1446         return res;
1447 }
1448
1449 static ir_node *gen_Unknown(ir_node *node)
1450 {
1451         ir_node  *block     = get_nodes_block(node);
1452         ir_node  *new_block = be_transform_node(block);
1453         dbg_info *dbgi      = get_irn_dbg_info(node);
1454
1455         /* just produce a 0 */
1456         ir_mode *mode = get_irn_mode(node);
1457         if (mode_is_float(mode)) {
1458                 tarval *tv = get_mode_null(mode);
1459                 ir_node *node = new_bd_arm_fpaConst(dbgi, new_block, tv);
1460                 be_dep_on_frame(node);
1461                 return node;
1462         } else if (mode_needs_gp_reg(mode)) {
1463                 return create_const_graph_value(dbgi, new_block, 0);
1464         }
1465
1466         panic("Unexpected Unknown mode");
1467 }
1468
1469 /**
1470  * Change some phi modes
1471  */
1472 static ir_node *gen_Phi(ir_node *node)
1473 {
1474         const arch_register_req_t *req;
1475         ir_node  *block = be_transform_node(get_nodes_block(node));
1476         ir_graph *irg   = current_ir_graph;
1477         dbg_info *dbgi  = get_irn_dbg_info(node);
1478         ir_mode  *mode  = get_irn_mode(node);
1479         ir_node  *phi;
1480
1481         if (mode_needs_gp_reg(mode)) {
1482                 /* we shouldn't have any 64bit stuff around anymore */
1483                 assert(get_mode_size_bits(mode) <= 32);
1484                 /* all integer operations are on 32bit registers now */
1485                 mode = mode_Iu;
1486                 req  = arm_reg_classes[CLASS_arm_gp].class_req;
1487         } else {
1488                 req = arch_no_register_req;
1489         }
1490
1491         /* phi nodes allow loops, so we use the old arguments for now
1492          * and fix this later */
1493         phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node),
1494                           get_irn_in(node) + 1);
1495         copy_node_attr(irg, node, phi);
1496         be_duplicate_deps(node, phi);
1497
1498         arch_set_out_register_req(phi, 0, req);
1499
1500         be_enqueue_preds(node);
1501
1502         return phi;
1503 }
1504
1505 /**
1506  * the BAD transformer.
1507  */
1508 static ir_node *bad_transform(ir_node *irn)
1509 {
1510         panic("ARM backend: unexpected node %+F", irn);
1511 }
1512
1513 /**
1514  * Set a node emitter. Make it a bit more type safe.
1515  */
1516 static void set_transformer(ir_op *op, be_transform_func arm_transform_func)
1517 {
1518         op->ops.generic = (op_func)arm_transform_func;
1519 }
1520
1521 /**
1522  * Enters all transform functions into the generic pointer
1523  */
1524 static void arm_register_transformers(void)
1525 {
1526         /* first clear the generic function pointer for all ops */
1527         clear_irp_opcodes_generic_func();
1528
1529         set_transformer(op_Abs,          gen_Abs);
1530         set_transformer(op_Add,          gen_Add);
1531         set_transformer(op_And,          gen_And);
1532         set_transformer(op_be_AddSP,     gen_be_AddSP);
1533         set_transformer(op_be_Call,      gen_be_Call);
1534         set_transformer(op_be_Copy,      gen_be_Copy);
1535         set_transformer(op_be_FrameAddr, gen_be_FrameAddr);
1536         set_transformer(op_be_SubSP,     gen_be_SubSP);
1537         set_transformer(op_Cmp,          gen_Cmp);
1538         set_transformer(op_Cond,         gen_Cond);
1539         set_transformer(op_Const,        gen_Const);
1540         set_transformer(op_Conv,         gen_Conv);
1541         set_transformer(op_CopyB,        gen_CopyB);
1542         set_transformer(op_Eor,          gen_Eor);
1543         set_transformer(op_Jmp,          gen_Jmp);
1544         set_transformer(op_Load,         gen_Load);
1545         set_transformer(op_Minus,        gen_Minus);
1546         set_transformer(op_Mul,          gen_Mul);
1547         set_transformer(op_Not,          gen_Not);
1548         set_transformer(op_Or,           gen_Or);
1549         set_transformer(op_Phi,          gen_Phi);
1550         set_transformer(op_Proj,         gen_Proj);
1551         set_transformer(op_Quot,         gen_Quot);
1552         set_transformer(op_Rotl,         gen_Rotl);
1553         set_transformer(op_Shl,          gen_Shl);
1554         set_transformer(op_Shr,          gen_Shr);
1555         set_transformer(op_Shrs,         gen_Shrs);
1556         set_transformer(op_Store,        gen_Store);
1557         set_transformer(op_Sub,          gen_Sub);
1558         set_transformer(op_SymConst,     gen_SymConst);
1559         set_transformer(op_Unknown,      gen_Unknown);
1560
1561         set_transformer(op_ASM,       bad_transform);
1562         set_transformer(op_Builtin,   bad_transform);
1563         set_transformer(op_CallBegin, bad_transform);
1564         set_transformer(op_Cast,      bad_transform);
1565         set_transformer(op_Confirm,   bad_transform);
1566         set_transformer(op_DivMod,    bad_transform);
1567         set_transformer(op_EndExcept, bad_transform);
1568         set_transformer(op_EndReg,    bad_transform);
1569         set_transformer(op_Filter,    bad_transform);
1570         set_transformer(op_Free,      bad_transform);
1571         set_transformer(op_Id,        bad_transform);
1572         set_transformer(op_InstOf,    bad_transform);
1573         set_transformer(op_Mulh,      bad_transform);
1574         set_transformer(op_Mux,       bad_transform);
1575         set_transformer(op_Raise,     bad_transform);
1576         set_transformer(op_Sel,       bad_transform);
1577         set_transformer(op_Tuple,     bad_transform);
1578 }
1579
1580 /**
1581  * Initialize fpa Immediate support.
1582  */
1583 static void arm_init_fpa_immediate(void)
1584 {
1585         /* 0, 1, 2, 3, 4, 5, 10, or 0.5. */
1586         fpa_imm[0][fpa_null]  = get_mode_null(mode_F);
1587         fpa_imm[0][fpa_one]   = get_mode_one(mode_F);
1588         fpa_imm[0][fpa_two]   = new_tarval_from_str("2", 1, mode_F);
1589         fpa_imm[0][fpa_three] = new_tarval_from_str("3", 1, mode_F);
1590         fpa_imm[0][fpa_four]  = new_tarval_from_str("4", 1, mode_F);
1591         fpa_imm[0][fpa_five]  = new_tarval_from_str("5", 1, mode_F);
1592         fpa_imm[0][fpa_ten]   = new_tarval_from_str("10", 2, mode_F);
1593         fpa_imm[0][fpa_half]  = new_tarval_from_str("0.5", 3, mode_F);
1594
1595         fpa_imm[1][fpa_null]  = get_mode_null(mode_D);
1596         fpa_imm[1][fpa_one]   = get_mode_one(mode_D);
1597         fpa_imm[1][fpa_two]   = new_tarval_from_str("2", 1, mode_D);
1598         fpa_imm[1][fpa_three] = new_tarval_from_str("3", 1, mode_D);
1599         fpa_imm[1][fpa_four]  = new_tarval_from_str("4", 1, mode_D);
1600         fpa_imm[1][fpa_five]  = new_tarval_from_str("5", 1, mode_D);
1601         fpa_imm[1][fpa_ten]   = new_tarval_from_str("10", 2, mode_D);
1602         fpa_imm[1][fpa_half]  = new_tarval_from_str("0.5", 3, mode_D);
1603
1604         fpa_imm[2][fpa_null]  = get_mode_null(mode_E);
1605         fpa_imm[2][fpa_one]   = get_mode_one(mode_E);
1606         fpa_imm[2][fpa_two]   = new_tarval_from_str("2", 1, mode_E);
1607         fpa_imm[2][fpa_three] = new_tarval_from_str("3", 1, mode_E);
1608         fpa_imm[2][fpa_four]  = new_tarval_from_str("4", 1, mode_E);
1609         fpa_imm[2][fpa_five]  = new_tarval_from_str("5", 1, mode_E);
1610         fpa_imm[2][fpa_ten]   = new_tarval_from_str("10", 2, mode_E);
1611         fpa_imm[2][fpa_half]  = new_tarval_from_str("0.5", 3, mode_E);
1612 }
1613
1614 /**
1615  * Transform a Firm graph into an ARM graph.
1616  */
1617 void arm_transform_graph(arm_code_gen_t *cg)
1618 {
1619         static int imm_initialized = 0;
1620
1621         if (! imm_initialized) {
1622                 arm_init_fpa_immediate();
1623                 imm_initialized = 1;
1624         }
1625         arm_register_transformers();
1626         env_cg = cg;
1627         be_transform_graph(cg->irg, NULL);
1628 }
1629
1630 void arm_init_transform(void)
1631 {
1632         FIRM_DBG_REGISTER(dbg, "firm.be.arm.transform");
1633 }