- remove block parameter from new_r_Proj and new_rd_Proj
[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(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_is_negative(tv)) {
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  *load     = get_Proj_pred(node);
1230         ir_node  *new_load = be_transform_node(load);
1231         dbg_info *dbgi     = get_irn_dbg_info(node);
1232         long     proj      = get_Proj_proj(node);
1233
1234         /* renumber the proj */
1235         switch (get_arm_irn_opcode(new_load)) {
1236         case iro_arm_Ldr:
1237                 /* handle all gp loads equal: they have the same proj numbers. */
1238                 if (proj == pn_Load_res) {
1239                         return new_rd_Proj(dbgi, new_load, mode_Iu, pn_arm_Ldr_res);
1240                 } else if (proj == pn_Load_M) {
1241                         return new_rd_Proj(dbgi, new_load, mode_M, pn_arm_Ldr_M);
1242                 }
1243                 break;
1244         case iro_arm_fpaLdf:
1245                 if (proj == pn_Load_res) {
1246                         ir_mode *mode = get_Load_mode(load);
1247                         return new_rd_Proj(dbgi, new_load, mode, pn_arm_fpaLdf_res);
1248                 } else if (proj == pn_Load_M) {
1249                         return new_rd_Proj(dbgi, new_load, mode_M, pn_arm_fpaLdf_M);
1250                 }
1251                 break;
1252         default:
1253                 break;
1254         }
1255         panic("Unsupported Proj from Load");
1256 }
1257
1258 /**
1259  * Transform and renumber the Projs from a CopyB.
1260  */
1261 static ir_node *gen_Proj_CopyB(ir_node *node)
1262 {
1263         ir_node  *pred     = get_Proj_pred(node);
1264         ir_node  *new_pred = be_transform_node(pred);
1265         dbg_info *dbgi     = get_irn_dbg_info(node);
1266         long     proj      = get_Proj_proj(node);
1267
1268         switch (proj) {
1269         case pn_CopyB_M_regular:
1270                 if (is_arm_CopyB(new_pred)) {
1271                         return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_CopyB_M);
1272                 }
1273                 break;
1274         default:
1275                 break;
1276         }
1277         panic("Unsupported Proj from CopyB");
1278 }
1279
1280 /**
1281  * Transform and renumber the Projs from a Quot.
1282  */
1283 static ir_node *gen_Proj_Quot(ir_node *node)
1284 {
1285         ir_node  *pred     = get_Proj_pred(node);
1286         ir_node  *new_pred = be_transform_node(pred);
1287         dbg_info *dbgi     = get_irn_dbg_info(node);
1288         ir_mode  *mode     = get_irn_mode(node);
1289         long     proj      = get_Proj_proj(node);
1290
1291         switch (proj) {
1292         case pn_Quot_M:
1293                 if (is_arm_fpaDvf(new_pred)) {
1294                         return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_fpaDvf_M);
1295                 } else if (is_arm_fpaRdf(new_pred)) {
1296                         return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_fpaRdf_M);
1297                 } else if (is_arm_fpaFdv(new_pred)) {
1298                         return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_fpaFdv_M);
1299                 } else if (is_arm_fpaFrd(new_pred)) {
1300                         return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_fpaFrd_M);
1301                 }
1302                 break;
1303         case pn_Quot_res:
1304                 if (is_arm_fpaDvf(new_pred)) {
1305                         return new_rd_Proj(dbgi, new_pred, mode, pn_arm_fpaDvf_res);
1306                 } else if (is_arm_fpaRdf(new_pred)) {
1307                         return new_rd_Proj(dbgi, new_pred, mode, pn_arm_fpaRdf_res);
1308                 } else if (is_arm_fpaFdv(new_pred)) {
1309                         return new_rd_Proj(dbgi, new_pred, mode, pn_arm_fpaFdv_res);
1310                 } else if (is_arm_fpaFrd(new_pred)) {
1311                         return new_rd_Proj(dbgi, new_pred, mode, pn_arm_fpaFrd_res);
1312                 }
1313                 break;
1314         default:
1315                 break;
1316         }
1317         panic("Unsupported Proj from Quot");
1318 }
1319
1320 /**
1321  * Transform the Projs of a be_AddSP.
1322  */
1323 static ir_node *gen_Proj_be_AddSP(ir_node *node)
1324 {
1325         ir_node  *pred     = get_Proj_pred(node);
1326         ir_node  *new_pred = be_transform_node(pred);
1327         dbg_info *dbgi     = get_irn_dbg_info(node);
1328         long     proj      = get_Proj_proj(node);
1329
1330         if (proj == pn_be_AddSP_sp) {
1331                 ir_node *res = new_rd_Proj(dbgi, new_pred, mode_Iu,
1332                                            pn_arm_SubSPandCopy_stack);
1333                 arch_set_irn_register(res, &arm_gp_regs[REG_SP]);
1334                 return res;
1335         } else if (proj == pn_be_AddSP_res) {
1336                 return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_arm_SubSPandCopy_addr);
1337         } else if (proj == pn_be_AddSP_M) {
1338                 return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_SubSPandCopy_M);
1339         }
1340         panic("Unsupported Proj from AddSP");
1341 }
1342
1343 /**
1344  * Transform the Projs of a be_SubSP.
1345  */
1346 static ir_node *gen_Proj_be_SubSP(ir_node *node)
1347 {
1348         ir_node  *pred     = get_Proj_pred(node);
1349         ir_node  *new_pred = be_transform_node(pred);
1350         dbg_info *dbgi     = get_irn_dbg_info(node);
1351         long     proj      = get_Proj_proj(node);
1352
1353         if (proj == pn_be_SubSP_sp) {
1354                 ir_node *res = new_rd_Proj(dbgi, new_pred, mode_Iu,
1355                                            pn_arm_AddSP_stack);
1356                 arch_set_irn_register(res, &arm_gp_regs[REG_SP]);
1357                 return res;
1358         } else if (proj == pn_be_SubSP_M) {
1359                 return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_AddSP_M);
1360         }
1361         panic("Unsupported Proj from SubSP");
1362 }
1363
1364 /**
1365  * Transform the Projs from a Cmp.
1366  */
1367 static ir_node *gen_Proj_Cmp(ir_node *node)
1368 {
1369         (void) node;
1370         panic("Mux NYI");
1371 }
1372
1373
1374 /**
1375  * Transform the Thread Local Storage Proj.
1376  */
1377 static ir_node *gen_Proj_tls(ir_node *node)
1378 {
1379         ir_node  *block = be_transform_node(get_nodes_block(node));
1380         dbg_info *dbgi  = NULL;
1381
1382         return new_bd_arm_LdTls(dbgi, block, mode_Iu);
1383 }
1384
1385 /**
1386  * Transform a Proj node.
1387  */
1388 static ir_node *gen_Proj(ir_node *node)
1389 {
1390         ir_graph *irg  = current_ir_graph;
1391         dbg_info *dbgi = get_irn_dbg_info(node);
1392         ir_node  *pred = get_Proj_pred(node);
1393         long     proj  = get_Proj_proj(node);
1394
1395         if (is_Store(pred)) {
1396                 if (proj == pn_Store_M) {
1397                         return be_transform_node(pred);
1398                 } else {
1399                         panic("Unsupported Proj from Store");
1400                 }
1401         } else if (is_Load(pred)) {
1402                 return gen_Proj_Load(node);
1403         } else if (is_CopyB(pred)) {
1404                 return gen_Proj_CopyB(node);
1405         } else if (is_Quot(pred)) {
1406                 return gen_Proj_Quot(node);
1407         } else if (be_is_SubSP(pred)) {
1408                 return gen_Proj_be_SubSP(node);
1409         } else if (be_is_AddSP(pred)) {
1410                 return gen_Proj_be_AddSP(node);
1411         } else if (is_Cmp(pred)) {
1412                 return gen_Proj_Cmp(node);
1413         } else if (is_Start(pred)) {
1414                 if (proj == pn_Start_X_initial_exec) {
1415                         ir_node *block = get_nodes_block(pred);
1416                         ir_node *jump;
1417
1418                         /* we exchange the ProjX with a jump */
1419                         block = be_transform_node(block);
1420                         jump  = new_rd_Jmp(dbgi, block);
1421                         return jump;
1422                 }
1423                 if (node == get_irg_anchor(irg, anchor_tls)) {
1424                         return gen_Proj_tls(node);
1425                 }
1426         } else {
1427                 ir_node *new_pred = be_transform_node(pred);
1428                 ir_mode *mode     = get_irn_mode(node);
1429                 if (mode_needs_gp_reg(mode)) {
1430                         ir_node *new_proj = new_r_Proj(new_pred, mode_Iu,
1431                                                        get_Proj_proj(node));
1432                         new_proj->node_nr = node->node_nr;
1433                         return new_proj;
1434                 }
1435         }
1436
1437         return be_duplicate_node(node);
1438 }
1439
1440 typedef ir_node *(*create_const_node_func)(dbg_info *db, ir_node *block);
1441
1442 static inline ir_node *create_const(ir_node **place,
1443                                     create_const_node_func func,
1444                                     const arch_register_t* reg)
1445 {
1446         ir_node *block, *res;
1447
1448         if (*place != NULL)
1449                 return *place;
1450
1451         block = get_irg_start_block(env_cg->irg);
1452         res = func(NULL, block);
1453         arch_set_irn_register(res, reg);
1454         *place = res;
1455         return res;
1456 }
1457
1458 static ir_node *gen_Unknown(ir_node *node)
1459 {
1460         ir_node  *block     = get_nodes_block(node);
1461         ir_node  *new_block = be_transform_node(block);
1462         dbg_info *dbgi      = get_irn_dbg_info(node);
1463
1464         /* just produce a 0 */
1465         ir_mode *mode = get_irn_mode(node);
1466         if (mode_is_float(mode)) {
1467                 tarval *tv = get_mode_null(mode);
1468                 ir_node *node = new_bd_arm_fpaConst(dbgi, new_block, tv);
1469                 be_dep_on_frame(node);
1470                 return node;
1471         } else if (mode_needs_gp_reg(mode)) {
1472                 return create_const_graph_value(dbgi, new_block, 0);
1473         }
1474
1475         panic("Unexpected Unknown mode");
1476 }
1477
1478 /**
1479  * Change some phi modes
1480  */
1481 static ir_node *gen_Phi(ir_node *node)
1482 {
1483         const arch_register_req_t *req;
1484         ir_node  *block = be_transform_node(get_nodes_block(node));
1485         ir_graph *irg   = current_ir_graph;
1486         dbg_info *dbgi  = get_irn_dbg_info(node);
1487         ir_mode  *mode  = get_irn_mode(node);
1488         ir_node  *phi;
1489
1490         if (mode_needs_gp_reg(mode)) {
1491                 /* we shouldn't have any 64bit stuff around anymore */
1492                 assert(get_mode_size_bits(mode) <= 32);
1493                 /* all integer operations are on 32bit registers now */
1494                 mode = mode_Iu;
1495                 req  = arm_reg_classes[CLASS_arm_gp].class_req;
1496         } else {
1497                 req = arch_no_register_req;
1498         }
1499
1500         /* phi nodes allow loops, so we use the old arguments for now
1501          * and fix this later */
1502         phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node),
1503                           get_irn_in(node) + 1);
1504         copy_node_attr(node, phi);
1505         be_duplicate_deps(node, phi);
1506
1507         arch_set_out_register_req(phi, 0, req);
1508
1509         be_enqueue_preds(node);
1510
1511         return phi;
1512 }
1513
1514 /**
1515  * the BAD transformer.
1516  */
1517 static ir_node *bad_transform(ir_node *irn)
1518 {
1519         panic("ARM backend: Not implemented: %+F", irn);
1520 }
1521
1522 /**
1523  * Set a node emitter. Make it a bit more type safe.
1524  */
1525 static void set_transformer(ir_op *op, be_transform_func arm_transform_func)
1526 {
1527         op->ops.generic = (op_func)arm_transform_func;
1528 }
1529
1530 /**
1531  * Enters all transform functions into the generic pointer
1532  */
1533 static void arm_register_transformers(void)
1534 {
1535         /* first clear the generic function pointer for all ops */
1536         clear_irp_opcodes_generic_func();
1537
1538         set_transformer(op_Abs,          gen_Abs);
1539         set_transformer(op_Add,          gen_Add);
1540         set_transformer(op_And,          gen_And);
1541         set_transformer(op_be_AddSP,     gen_be_AddSP);
1542         set_transformer(op_be_Call,      gen_be_Call);
1543         set_transformer(op_be_Copy,      gen_be_Copy);
1544         set_transformer(op_be_FrameAddr, gen_be_FrameAddr);
1545         set_transformer(op_be_SubSP,     gen_be_SubSP);
1546         set_transformer(op_Cmp,          gen_Cmp);
1547         set_transformer(op_Cond,         gen_Cond);
1548         set_transformer(op_Const,        gen_Const);
1549         set_transformer(op_Conv,         gen_Conv);
1550         set_transformer(op_CopyB,        gen_CopyB);
1551         set_transformer(op_Eor,          gen_Eor);
1552         set_transformer(op_Jmp,          gen_Jmp);
1553         set_transformer(op_Load,         gen_Load);
1554         set_transformer(op_Minus,        gen_Minus);
1555         set_transformer(op_Mul,          gen_Mul);
1556         set_transformer(op_Not,          gen_Not);
1557         set_transformer(op_Or,           gen_Or);
1558         set_transformer(op_Phi,          gen_Phi);
1559         set_transformer(op_Proj,         gen_Proj);
1560         set_transformer(op_Quot,         gen_Quot);
1561         set_transformer(op_Rotl,         gen_Rotl);
1562         set_transformer(op_Shl,          gen_Shl);
1563         set_transformer(op_Shr,          gen_Shr);
1564         set_transformer(op_Shrs,         gen_Shrs);
1565         set_transformer(op_Store,        gen_Store);
1566         set_transformer(op_Sub,          gen_Sub);
1567         set_transformer(op_SymConst,     gen_SymConst);
1568         set_transformer(op_Unknown,      gen_Unknown);
1569
1570         set_transformer(op_ASM,       bad_transform);
1571         set_transformer(op_Builtin,   bad_transform);
1572         set_transformer(op_CallBegin, bad_transform);
1573         set_transformer(op_Cast,      bad_transform);
1574         set_transformer(op_Confirm,   bad_transform);
1575         set_transformer(op_DivMod,    bad_transform);
1576         set_transformer(op_EndExcept, bad_transform);
1577         set_transformer(op_EndReg,    bad_transform);
1578         set_transformer(op_Filter,    bad_transform);
1579         set_transformer(op_Free,      bad_transform);
1580         set_transformer(op_Id,        bad_transform);
1581         set_transformer(op_InstOf,    bad_transform);
1582         set_transformer(op_Mulh,      bad_transform);
1583         set_transformer(op_Mux,       bad_transform);
1584         set_transformer(op_Raise,     bad_transform);
1585         set_transformer(op_Sel,       bad_transform);
1586         set_transformer(op_Tuple,     bad_transform);
1587 }
1588
1589 /**
1590  * Pre-transform all unknown nodes.
1591  */
1592 static void arm_pretransform_node(void)
1593 {
1594         arm_code_gen_t *cg = env_cg;
1595
1596         cg->unknown_gp  = be_pre_transform_node(cg->unknown_gp);
1597         cg->unknown_fpa = be_pre_transform_node(cg->unknown_fpa);
1598 }
1599
1600 /**
1601  * Initialize fpa Immediate support.
1602  */
1603 static void arm_init_fpa_immediate(void)
1604 {
1605         /* 0, 1, 2, 3, 4, 5, 10, or 0.5. */
1606         fpa_imm[0][fpa_null]  = get_mode_null(mode_F);
1607         fpa_imm[0][fpa_one]   = get_mode_one(mode_F);
1608         fpa_imm[0][fpa_two]   = new_tarval_from_str("2", 1, mode_F);
1609         fpa_imm[0][fpa_three] = new_tarval_from_str("3", 1, mode_F);
1610         fpa_imm[0][fpa_four]  = new_tarval_from_str("4", 1, mode_F);
1611         fpa_imm[0][fpa_five]  = new_tarval_from_str("5", 1, mode_F);
1612         fpa_imm[0][fpa_ten]   = new_tarval_from_str("10", 2, mode_F);
1613         fpa_imm[0][fpa_half]  = new_tarval_from_str("0.5", 3, mode_F);
1614
1615         fpa_imm[1][fpa_null]  = get_mode_null(mode_D);
1616         fpa_imm[1][fpa_one]   = get_mode_one(mode_D);
1617         fpa_imm[1][fpa_two]   = new_tarval_from_str("2", 1, mode_D);
1618         fpa_imm[1][fpa_three] = new_tarval_from_str("3", 1, mode_D);
1619         fpa_imm[1][fpa_four]  = new_tarval_from_str("4", 1, mode_D);
1620         fpa_imm[1][fpa_five]  = new_tarval_from_str("5", 1, mode_D);
1621         fpa_imm[1][fpa_ten]   = new_tarval_from_str("10", 2, mode_D);
1622         fpa_imm[1][fpa_half]  = new_tarval_from_str("0.5", 3, mode_D);
1623
1624         fpa_imm[2][fpa_null]  = get_mode_null(mode_E);
1625         fpa_imm[2][fpa_one]   = get_mode_one(mode_E);
1626         fpa_imm[2][fpa_two]   = new_tarval_from_str("2", 1, mode_E);
1627         fpa_imm[2][fpa_three] = new_tarval_from_str("3", 1, mode_E);
1628         fpa_imm[2][fpa_four]  = new_tarval_from_str("4", 1, mode_E);
1629         fpa_imm[2][fpa_five]  = new_tarval_from_str("5", 1, mode_E);
1630         fpa_imm[2][fpa_ten]   = new_tarval_from_str("10", 2, mode_E);
1631         fpa_imm[2][fpa_half]  = new_tarval_from_str("0.5", 3, mode_E);
1632 }
1633
1634 /**
1635  * Transform a Firm graph into an ARM graph.
1636  */
1637 void arm_transform_graph(arm_code_gen_t *cg)
1638 {
1639         static int imm_initialized = 0;
1640
1641         if (! imm_initialized) {
1642                 arm_init_fpa_immediate();
1643                 imm_initialized = 1;
1644         }
1645         arm_register_transformers();
1646         env_cg = cg;
1647         be_transform_graph(cg->birg, arm_pretransform_node);
1648 }
1649
1650 void arm_init_transform(void)
1651 {
1652         FIRM_DBG_REGISTER(dbg, "firm.be.arm.transform");
1653 }