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