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