Changed transformer to be like ia32: do a transform- and copy
[libfirm] / ir / be / arm / arm_transform.c
1 /*
2  * Copyright (C) 1995-2007 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 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "irnode_t.h"
31 #include "irgraph_t.h"
32 #include "irmode_t.h"
33 #include "irgmod.h"
34 #include "iredges.h"
35 #include "irvrfy.h"
36 #include "ircons.h"
37 #include "irprintf.h"
38 #include "dbginfo.h"
39 #include "iropt_t.h"
40 #include "debug.h"
41 #include "error.h"
42
43 #include "../benode_t.h"
44 #include "../beirg_t.h"
45 #include "../betranshlp.h"
46 #include "bearch_arm_t.h"
47
48 #include "arm_nodes_attr.h"
49 #include "archop.h"
50 #include "arm_transform.h"
51 #include "arm_new_nodes.h"
52 #include "arm_map_regs.h"
53
54 #include "gen_arm_regalloc_if.h"
55
56 #include <limits.h>
57
58
59 /** hold the current code generator during transformation */
60 static arm_code_gen_t *env_cg;
61
62 extern ir_op *get_op_Mulh(void);
63
64
65 /****************************************************************************************************
66  *                  _        _                        __                           _   _
67  *                 | |      | |                      / _|                         | | (_)
68  *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
69  * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
70  * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
71  * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
72  *
73  ****************************************************************************************************/
74
75 static INLINE int mode_needs_gp_reg(ir_mode *mode) {
76         return mode_is_int(mode) || mode_is_character(mode) || mode_is_reference(mode);
77 }
78
79 typedef struct vals_ {
80         int ops;
81         unsigned char values[4];
82         unsigned char shifts[4];
83 } vals;
84
85 /** Execute ROL. */
86 static unsigned do_rol(unsigned v, unsigned rol) {
87         return (v << rol) | (v >> (32 - rol));
88 }
89
90 /**
91  * construct 8bit values and rot amounts for a value
92  */
93 static void gen_vals_from_word(unsigned int value, vals *result)
94 {
95         int initial = 0;
96
97         memset(result, 0, sizeof(*result));
98
99         /* special case: we prefer shift amount 0 */
100         if (value < 0x100) {
101                 result->values[0] = value;
102                 result->ops       = 1;
103                 return;
104         }
105
106         while (value != 0) {
107                 if (value & 0xFF) {
108                         unsigned v = do_rol(value, 8) & 0xFFFFFF;
109                         int shf = 0;
110                         for (;;) {
111                                 if ((v & 3) != 0)
112                                         break;
113                                 shf += 2;
114                                 v >>= 2;
115                         }
116                         v  &= 0xFF;
117                         shf = (initial + shf - 8) & 0x1F;
118                         result->values[result->ops] = v;
119                         result->shifts[result->ops] = shf;
120                         ++result->ops;
121
122                         value ^= do_rol(v, shf) >> initial;
123                 }
124                 else {
125                         value >>= 8;
126                         initial += 8;
127                 }
128         }
129 }
130
131 /**
132  * Creates a arm_Const node.
133  */
134 static ir_node *create_const_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) {
135         tarval   *tv   = new_tarval_from_long(value, mode_Iu);
136         dbg_info *dbg  = get_irn_dbg_info(irn);
137         ir_mode  *mode = get_irn_mode(irn);
138         ir_node *res;
139
140         if (mode_needs_gp_reg(mode))
141                 mode = mode_Iu;
142         res = new_rd_arm_Mov_i(dbg, current_ir_graph, block, mode, tv);
143         /* ensure the const is schedules AFTER the barrier */
144         add_irn_dep(res, be_abi_get_start_barrier(abi));
145         return res;
146 }
147
148 /**
149  * Creates a arm_Const_Neg node.
150  */
151 static ir_node *create_const_neg_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) {
152         tarval   *tv   = new_tarval_from_long(value, mode_Iu);
153         dbg_info *dbg  = get_irn_dbg_info(irn);
154         ir_mode  *mode = get_irn_mode(irn);
155         ir_node *res;
156
157         if (mode_needs_gp_reg(mode))
158                 mode = mode_Iu;
159         res = new_rd_arm_Mvn_i(dbg, current_ir_graph, block, mode, tv);
160         add_irn_dep(res, be_abi_get_start_barrier(abi));
161         /* ensure the const is schedules AFTER the barrier */
162         return res;
163 }
164
165 #define NEW_BINOP_NODE(opname, env, op1, op2) new_rd_arm_##opname(env->dbg, current_ir_graph, env->block, op1, op2, env->mode)
166
167 /**
168  * Encodes an immediate with shifter operand
169  */
170 static unsigned int arm_encode_imm_w_shift(unsigned int shift, unsigned int immediate) {
171         return immediate | ((shift>>1)<<8);
172 }
173
174 /**
175  * Decode an immediate with shifter operand
176  */
177 unsigned int arm_decode_imm_w_shift(tarval *tv) {
178         unsigned l = get_tarval_long(tv);
179         unsigned rol = (l & ~0xFF) >> 7;
180
181         return do_rol(l & 0xFF, rol);
182 }
183
184 /**
185  * Creates a possible DAG for an constant.
186  */
187 static ir_node *create_const_graph_value(be_abi_irg_t *abi, ir_node *irn, ir_node *block, unsigned int value) {
188         ir_node *result;
189         vals v, vn;
190         int cnt;
191         ir_mode *mode = get_irn_mode(irn);
192         dbg_info *dbg = get_irn_dbg_info(irn);
193
194         gen_vals_from_word(value, &v);
195         gen_vals_from_word(~value, &vn);
196
197         if (mode_needs_gp_reg(mode))
198                 mode = mode_Iu;
199
200         if (vn.ops < v.ops) {
201                 /* remove bits */
202                 result = create_const_neg_node(abi, irn, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
203
204                 for (cnt = 1; cnt < vn.ops; ++cnt) {
205                         tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]), mode_Iu);
206                         ir_node *bic_i_node = new_rd_arm_Bic_i(dbg, current_ir_graph, block, result, mode, tv);
207                         result = bic_i_node;
208                 }
209         }
210         else {
211                 /* add bits */
212                 result = create_const_node(abi, irn, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
213
214                 for (cnt = 1; cnt < v.ops; ++cnt) {
215                         tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]), mode_Iu);
216                         ir_node *orr_i_node = new_rd_arm_Or_i(dbg, current_ir_graph, block, result, mode, tv);
217                         result = orr_i_node;
218                 }
219         }
220         return result;
221 }
222
223 /**
224  * Create a DAG constructing a given Const.
225  *
226  * @param irn  a Firm const
227  */
228 static ir_node *create_const_graph(be_abi_irg_t *abi, ir_node *irn, ir_node *block) {
229         tarval  *tv = get_Const_tarval(irn);
230         ir_mode *mode = get_tarval_mode(tv);
231         int     value;
232
233         if (mode_is_reference(mode)) {
234                 /* ARM is 32bit, so we can safely convert a reference tarval into Iu */
235                 assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_Iu));
236                 tv = tarval_convert_to(tv, mode_Iu);
237         }
238         value = get_tarval_long(tv);
239         return create_const_graph_value(abi, irn, block, value);
240 }
241
242 /**
243  * Creates code for a Firm Const node.
244  */
245 static ir_node *gen_arm_Const(ir_node *irn, ir_node *block, arm_code_gen_t *cg) {
246         ir_graph *irg = current_ir_graph;
247         ir_mode *mode = get_irn_mode(irn);
248         dbg_info *dbg = get_irn_dbg_info(irn);
249
250         if (mode_is_float(mode)) {
251                 cg->have_fp_insn = 1;
252                 if (USE_FPA(cg->isa)) {
253                         irn = new_rd_arm_fpaConst(dbg, irg, block, get_Const_tarval(irn));
254                         /* ensure the const is schedules AFTER the barrier */
255                         add_irn_dep(irn, be_abi_get_start_barrier(cg->birg->abi));
256                         return irn;
257                 }
258                 else if (USE_VFP(cg->isa))
259                         assert(mode != mode_E && "IEEE Extended FP not supported");
260                 assert(0 && "NYI");
261         }
262         return create_const_graph(cg->birg->abi, irn, block);
263 }
264
265 static ir_node *gen_mask(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) {
266         ir_node *block = get_nodes_block(irn);
267         unsigned mask_bits = (1 << result_bits) - 1;
268         ir_node *mask_node = create_const_graph_value(abi, irn, block, mask_bits);
269         dbg_info *dbg = get_irn_dbg_info(irn);
270         return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, get_irn_mode(irn), ARM_SHF_NONE, NULL);
271 }
272
273 static ir_node *gen_sign_extension(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) {
274         ir_node *block = get_nodes_block(irn);
275         int shift_width = 32 - result_bits;
276         ir_graph *irg = current_ir_graph;
277         ir_node *shift_const_node = create_const_graph_value(abi, irn, block, shift_width);
278         dbg_info *dbg = get_irn_dbg_info(irn);
279         ir_node *lshift_node = new_rd_arm_Shl(dbg, irg, block, op, shift_const_node, get_irn_mode(op));
280         ir_node *rshift_node = new_rd_arm_Shrs(dbg, irg, block, lshift_node, shift_const_node, get_irn_mode(irn));
281         return rshift_node;
282 }
283
284 /**
285  * Transforms a Conv node.
286  *
287  * @return The created ia32 Conv node
288  */
289 static ir_node *gen_Conv(ir_node *node) {
290         ir_node  *block    = be_transform_node(get_nodes_block(node));
291         ir_node  *op       = get_Conv_op(node);
292         ir_node  *new_op   = be_transform_node(op);
293         ir_graph *irg      = current_ir_graph;
294         ir_mode  *src_mode = get_irn_mode(op);
295         ir_mode  *dst_mode = get_irn_mode(node);
296         dbg_info *dbg      = get_irn_dbg_info(node);
297
298         if (mode_needs_gp_reg(dst_mode))
299                 dst_mode = mode_Iu;
300
301         if (src_mode == dst_mode)
302                 return new_op;
303
304         if (mode_is_float(src_mode) || mode_is_float(dst_mode)) {
305                 env_cg->have_fp_insn = 1;
306
307                 if (USE_FPA(env_cg->isa)) {
308                         if (mode_is_float(src_mode)) {
309                                 if (mode_is_float(dst_mode)) {
310                                         /* from float to float */
311                                         return new_rd_arm_fpaMov(dbg, irg, block, new_op, dst_mode);
312                                 }
313                                 else {
314                                         /* from float to int */
315                                         return new_rd_arm_fpaFix(dbg, irg, block, new_op, dst_mode);
316                                 }
317                         }
318                         else {
319                                 /* from int to float */
320                                 return new_rd_arm_fpaFlt(dbg, irg, block, new_op, dst_mode);
321                         }
322                 }
323                 else {
324                         panic("VFP not supported yet\n");
325                         return NULL;
326                 }
327         }
328         else { /* complete in gp registers */
329                 int src_bits = get_mode_size_bits(src_mode);
330                 int dst_bits = get_mode_size_bits(dst_mode);
331                 int src_sign = get_mode_sign(src_mode);
332                 int dst_sign = get_mode_sign(dst_mode);
333
334                 if (src_bits == dst_bits) {
335                         /* kill 32 -> 32 convs */
336                         if (src_bits == 32) {
337                                 return new_op;
338                         } else if (dst_bits < 32) {
339                         // 16 -> 16
340                                 // unsigned -> unsigned
341                                         // NOP
342                                 // unsigned -> signed
343                                         // sign extension (31:16)=(15)
344                                 // signed -> unsigned
345                                         // zero extension (31:16)=0
346                                 // signed -> signed
347                                         // NOP
348                                 if (src_sign && !dst_sign) {
349                                         return gen_mask(env_cg->birg->abi, node, new_op, dst_bits);
350                                 } else {
351                                         return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits);
352                                 }
353                         } else {
354                                 panic("Cannot handle mode %+F with %d bits\n", dst_mode, dst_bits);
355                                 return NULL;
356                         }
357                 }
358                 else if (src_bits < dst_bits) {
359                         // 16 -> 32
360                                 // unsigned -> unsigned
361                                         // NOP
362                                 // unsigned -> signed
363                                         // NOP
364                                 // signed -> unsigned
365                                         // sign extension (31:16)=(15)
366                                 // signed -> signed
367                                         // sign extension (31:16)=(15)
368                         if (src_sign) {
369                                 return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits);
370                         } else {
371                                 return new_op;
372                         }
373                 }
374                 else {
375                         // 32 -> 16
376                                 // unsigned -> unsigned
377                                         // maskieren (31:16)=0
378                                 // unsigned -> signed
379                                         // maskieren (31:16)=0
380                                 // signed -> unsigned
381                                         // maskieren (31:16)=0
382                                 // signed -> signed
383                                         // sign extension (erledigt auch maskieren) (31:16)=(15)
384                         if (src_sign && dst_sign) {
385                                 return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits);
386                         } else {
387                                 return gen_mask(env_cg->birg->abi, node, new_op, dst_bits);
388                         }
389                 }
390         }
391 }
392
393 /**
394  * Return true if an operand is a shifter operand
395  */
396 static int is_shifter_operand(ir_node *n, arm_shift_modifier *pmod) {
397         arm_shift_modifier mod = ARM_SHF_NONE;
398
399         if (is_arm_Mov(n))
400                 mod = get_arm_shift_modifier(n);
401
402         *pmod = mod;
403         if (mod != ARM_SHF_NONE) {
404                 long v = get_tarval_long(get_arm_value(n));
405                 if (v < 32)
406                         return (int)v;
407         }
408         return 0;
409 }
410
411 /**
412  * Creates an ARM Add.
413  *
414  * @return the created arm Add node
415  */
416 static ir_node *gen_Add(ir_node *node) {
417         ir_node  *block   = be_transform_node(get_nodes_block(node));
418         ir_node  *op1     = get_Add_left(node);
419         ir_node  *new_op1 = be_transform_node(op1);
420         ir_node  *op2     = get_Add_right(node);
421         ir_node  *new_op2 = be_transform_node(op2);
422         ir_mode  *mode    = get_irn_mode(node);
423         ir_graph *irg     = current_ir_graph;
424         ir_node  *new_op3;
425         int v;
426         arm_shift_modifier mod;
427         dbg_info *dbg = get_irn_dbg_info(node);
428
429         if (mode_is_float(mode)) {
430                 env_cg->have_fp_insn = 1;
431                 if (USE_FPA(env_cg->isa))
432                         return new_rd_arm_fpaAdd(dbg, irg, block, new_op1, new_op2, mode);
433                 else if (USE_VFP(env_cg->isa)) {
434                         assert(mode != mode_E && "IEEE Extended FP not supported");
435                         panic("VFP not supported yet\n");
436                         return NULL;
437                 }
438                 else {
439                         panic("Softfloat not supported yet\n");
440                         return NULL;
441                 }
442         } else {
443                 assert(mode_is_numP(mode));
444
445                 if (is_arm_Mov_i(new_op1))
446                         return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_value(op1));
447                 if (is_arm_Mov_i(new_op2))
448                         return new_rd_arm_Add_i(dbg, irg, block, new_op1, mode, get_arm_value(op2));
449
450                 /* check for MLA */
451                 if (is_arm_Mul(new_op1) && get_irn_n_edges(new_op1) == 1) {
452                         new_op3 = new_op2;
453                         op2 = get_irn_n(new_op1, 1);
454                         op1 = get_irn_n(new_op1, 0);
455
456                         return new_rd_arm_Mla(dbg, irg, block, new_op1, new_op2, new_op3, mode);
457                 }
458                 if (is_arm_Mul(new_op2) && get_irn_n_edges(new_op2) == 1) {
459                         new_op3 = new_op1;
460                         new_op1 = get_irn_n(new_op2, 0);
461                         new_op2 = get_irn_n(new_op2, 1);
462
463                         return new_rd_arm_Mla(dbg, irg, block, new_op1, new_op2, new_op3, mode);
464                 }
465
466                 /* is the first a shifter */
467                 v = is_shifter_operand(new_op1, &mod);
468                 if (v) {
469                         new_op1 = get_irn_n(new_op1, 0);
470                         return new_rd_arm_Add(dbg, irg, block, new_op2, new_op1, mode, mod, new_tarval_from_long(v, mode_Iu));
471                 }
472                 /* is the second a shifter */
473                 v = is_shifter_operand(new_op2, &mod);
474                 if (v) {
475                         new_op2 = get_irn_n(new_op2, 0);
476                         return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, mod, new_tarval_from_long(v, mode_Iu));
477                 }
478
479                 /* normal ADD */
480                 return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL);
481         }
482 }
483
484 /**
485  * Creates an ARM Mul.
486  *
487  * @return the created arm Mul node
488  */
489 static ir_node *gen_Mul(ir_node *node) {
490         ir_node  *block   = be_transform_node(get_nodes_block(node));
491         ir_node  *op1     = get_Mul_left(node);
492         ir_node  *new_op1 = be_transform_node(op1);
493         ir_node  *op2     = get_Mul_right(node);
494         ir_node  *new_op2 = be_transform_node(op2);
495         ir_mode  *mode    = get_irn_mode(node);
496         ir_graph *irg     = current_ir_graph;
497         dbg_info *dbg     = get_irn_dbg_info(node);
498
499         if (mode_is_float(mode)) {
500                 env_cg->have_fp_insn = 1;
501                 if (USE_FPA(env_cg->isa))
502                         return new_rd_arm_fpaMul(dbg, irg, 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\n");
506                 }
507                 else {
508                         panic("Softfloat not supported yet\n");
509                         return NULL;
510                 }
511         }
512         return new_rd_arm_Mul(dbg, irg, block, new_op1, new_op2, mode);
513 }
514
515 /**
516  * Creates an ARM floating point Div.
517  *
518  * @param env   The transformation environment
519  * @return the created arm fDiv node
520  */
521 static ir_node *gen_Quot(ir_node *node) {
522         ir_node  *block   = be_transform_node(get_nodes_block(node));
523         ir_node  *op1     = get_Quot_left(node);
524         ir_node  *new_op1 = be_transform_node(op1);
525         ir_node  *op2     = get_Quot_right(node);
526         ir_node  *new_op2 = be_transform_node(op2);
527         ir_mode  *mode    = get_irn_mode(node);
528         dbg_info *dbg     = get_irn_dbg_info(node);
529
530         assert(mode != mode_E && "IEEE Extended FP not supported");
531
532         env_cg->have_fp_insn = 1;
533         if (USE_FPA(env_cg->isa))
534                 return new_rd_arm_fpaDiv(dbg, current_ir_graph, block, op1, op2, mode);
535         else if (USE_VFP(env_cg->isa)) {
536                 assert(mode != mode_E && "IEEE Extended FP not supported");
537                 panic("VFP not supported yet\n");
538         }
539         else {
540                 panic("Softfloat not supported yet\n");
541                 return NULL;
542         }
543 }
544
545 #define GEN_INT_OP(op) \
546         ir_node  *block   = be_transform_node(get_nodes_block(node)); \
547         ir_node  *op1     = get_ ## op ## _left(node); \
548         ir_node  *new_op1 = be_transform_node(op1); \
549         ir_node  *op2     = get_ ## op ## _right(node); \
550         ir_node  *new_op2 = be_transform_node(op2); \
551         ir_graph *irg     = current_ir_graph; \
552         ir_mode  *mode    = get_irn_mode(node); \
553         dbg_info *dbg     = get_irn_dbg_info(node); \
554         int      v; \
555         arm_shift_modifier mod; \
556  \
557         if (is_arm_Mov_i(new_op1)) \
558                 return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1)); \
559         if (is_arm_Mov_i(new_op2)) \
560                 return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2)); \
561         /* is the first a shifter */ \
562         v = is_shifter_operand(new_op1, &mod); \
563         if (v) { \
564                 new_op1 = get_irn_n(new_op1, 0); \
565                 return new_rd_arm_ ## op(dbg, irg, block, new_op2, new_op1, mode, mod, new_tarval_from_long(v, mode_Iu)); \
566         } \
567         /* is the second a shifter */ \
568         v = is_shifter_operand(new_op2, &mod); \
569         if (v) { \
570                 new_op2 = get_irn_n(new_op2, 0); \
571                 return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, mod, new_tarval_from_long(v, mode_Iu)); \
572         } \
573         /* Normal op */ \
574         return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL) \
575
576 /**
577  * Creates an ARM And.
578  *
579  * @return the created arm And node
580  */
581 static ir_node *gen_And(ir_node *node) {
582         GEN_INT_OP(And);
583 }
584
585 /**
586  * Creates an ARM Orr.
587  *
588  * @param env   The transformation environment
589  * @return the created arm Or node
590  */
591 static ir_node *gen_Or(ir_node *node) {
592         GEN_INT_OP(Or);
593 }
594
595 /**
596  * Creates an ARM Eor.
597  *
598  * @return the created arm Eor node
599  */
600 static ir_node *gen_Eor(ir_node *node) {
601         GEN_INT_OP(Eor);
602 }
603
604 /**
605  * Creates an ARM Sub.
606  *
607  * @return the created arm Sub node
608  */
609 static ir_node *gen_Sub(ir_node *node) {
610         ir_node  *block   = be_transform_node(get_nodes_block(node));
611         ir_node  *op1     = get_Sub_left(node);
612         ir_node  *new_op1 = be_transform_node(op1);
613         ir_node  *op2     = get_Sub_right(node);
614         ir_node  *new_op2 = be_transform_node(node);
615         ir_mode  *mode    = get_irn_mode(node);
616         ir_graph *irg     = current_ir_graph;
617         dbg_info *dbg     = get_irn_dbg_info(node);
618         int      v;
619         arm_shift_modifier mod;
620
621         if (mode_is_float(mode)) {
622                 env_cg->have_fp_insn = 1;
623                 if (USE_FPA(env_cg->isa))
624                         return new_rd_arm_fpaSub(dbg, irg, block, new_op1, new_op2, mode);
625                 else if (USE_VFP(env_cg->isa)) {
626                         assert(mode != mode_E && "IEEE Extended FP not supported");
627                         panic("VFP not supported yet\n");
628                         return NULL;
629                 }
630                 else {
631                         panic("Softfloat not supported yet\n");
632                         return NULL;
633                 }
634         }
635         else {
636                 assert(mode_is_numP(mode) && "unknown mode for Sub");
637
638                 if (is_arm_Mov_i(new_op1))
639                         return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1));
640                 if (is_arm_Mov_i(new_op2))
641                         return new_rd_arm_Sub_i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2));
642
643                 /* is the first a shifter */
644                 v = is_shifter_operand(new_op1, &mod);
645                 if (v) {
646                         new_op1 = get_irn_n(new_op1, 0);
647                         return new_rd_arm_Rsb(dbg, irg, block, new_op2, new_op1, mode, mod, new_tarval_from_long(v, mode_Iu));
648                 }
649                 /* is the second a shifter */
650                 v = is_shifter_operand(new_op2, &mod);
651                 if (v) {
652                         new_op2 = get_irn_n(new_op2, 0);
653                         return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, mod, new_tarval_from_long(v, mode_Iu));
654                 }
655                 /* normal sub */
656                 return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL);
657         }
658 }
659
660 /**
661  * Creates an ARM Shl.
662  *
663  * @return the created ARM Shl node
664  */
665 static ir_node *gen_Shl(ir_node *node) {
666         ir_node  *block   = be_transform_node(get_nodes_block(node));
667         ir_node  *op1     = get_Shl_left(node);
668         ir_node  *new_op1 = be_transform_node(op1);
669         ir_node  *op2     = get_Shl_right(node);
670         ir_node  *new_op2 = be_transform_node(op2);
671         ir_mode  *mode    = get_irn_mode(node);
672         dbg_info *dbg     = get_irn_dbg_info(node);
673
674         if (is_arm_Mov_i(new_op2)) {
675                 return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSL, get_arm_value(new_op2));
676         }
677         return new_rd_arm_Shl(dbg, current_ir_graph, block, new_op1, new_op2, mode);
678 }
679
680 /**
681  * Creates an ARM Shr.
682  *
683  * @return the created ARM Shr node
684  */
685 static ir_node *gen_Shr(ir_node *node) {
686         ir_node  *block   = be_transform_node(get_nodes_block(node));
687         ir_node  *op1     = get_Shr_left(node);
688         ir_node  *new_op1 = be_transform_node(op1);
689         ir_node  *op2     = get_Shr_right(node);
690         ir_node  *new_op2 = be_transform_node(op2);
691         ir_mode  *mode    = get_irn_mode(node);
692         dbg_info *dbg     = get_irn_dbg_info(node);
693
694         if (is_arm_Mov_i(new_op2)) {
695                 return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSR, get_arm_value(new_op2));
696         }
697         return new_rd_arm_Shr(dbg, current_ir_graph, block, new_op1, new_op2, mode);
698 }
699
700 /**
701  * Creates an ARM Shrs.
702  *
703  * @return the created ARM Shrs node
704  */
705 static ir_node *gen_Shrs(ir_node *node) {
706         ir_node  *block   = be_transform_node(get_nodes_block(node));
707         ir_node  *op1     = get_Shrs_left(node);
708         ir_node  *new_op1 = be_transform_node(op1);
709         ir_node  *op2     = get_Shrs_right(node);
710         ir_node  *new_op2 = be_transform_node(op2);
711         ir_mode  *mode    = get_irn_mode(node);
712         dbg_info *dbg     = get_irn_dbg_info(node);
713
714         if (is_arm_Mov_i(new_op2)) {
715                 return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ASR, get_arm_value(op2));
716         }
717         return new_rd_arm_Shrs(dbg, current_ir_graph, block, new_op1, new_op2, mode);
718 }
719
720 /**
721  * Transforms a Not node.
722  *
723  * @return the created ARM Not node
724  */
725 static ir_node *gen_Not(ir_node *node) {
726         ir_node  *block   = be_transform_node(get_nodes_block(node));
727         ir_node  *op      = get_Not_op(node);
728         ir_node  *new_op  = be_transform_node(op);
729         dbg_info *dbg     = get_irn_dbg_info(node);
730         tarval   *tv      = NULL;
731         arm_shift_modifier mod = ARM_SHF_NONE;
732         int      v        = is_shifter_operand(new_op, &mod);
733
734         if (v) {
735                 new_op = get_irn_n(new_op, 0);
736                 tv = new_tarval_from_long(v, mode_Iu);
737         }
738         return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, get_irn_mode(node), mod, tv);
739 }
740
741 /**
742  * Transforms an Abs node.
743  *
744  * @param env   The transformation environment
745  * @return the created ARM Abs node
746  */
747 static ir_node *gen_Abs(ir_node *node) {
748         ir_node  *block   = be_transform_node(get_nodes_block(node));
749         ir_node  *op      = get_Not_op(node);
750         ir_node  *new_op  = be_transform_node(op);
751         dbg_info *dbg     = get_irn_dbg_info(node);
752         ir_mode  *mode    = get_irn_mode(node);
753
754         if (mode_is_float(mode)) {
755                 env_cg->have_fp_insn = 1;
756                 if (USE_FPA(env_cg->isa))
757                         return new_rd_arm_fpaAbs(dbg, current_ir_graph, block, new_op, mode);
758                 else if (USE_VFP(env_cg->isa)) {
759                         assert(mode != mode_E && "IEEE Extended FP not supported");
760                         assert(0 && "NYI");
761                 }
762         }
763         return new_rd_arm_Abs(dbg, current_ir_graph, block, new_op, mode);
764 }
765
766 /**
767  * Transforms a Minus node.
768  *
769  * @return the created ARM Minus node
770  */
771 static ir_node *gen_Minus(ir_node *node) {
772         ir_node  *block   = be_transform_node(get_nodes_block(node));
773         ir_node  *op      = get_Minus_op(node);
774         ir_node  *new_op  = be_transform_node(op);
775         dbg_info *dbg     = get_irn_dbg_info(node);
776         ir_mode  *mode    = get_irn_mode(node);
777
778         if (mode_is_float(mode)) {
779                 env_cg->have_fp_insn = 1;
780                 if (USE_FPA(env_cg->isa))
781                         return new_rd_arm_fpaMnv(dbg, current_ir_graph, block, op, mode);
782                 else if (USE_VFP(env_cg->isa)) {
783                         assert(mode != mode_E && "IEEE Extended FP not supported");
784                         assert(0 && "NYI");
785                 }
786         }
787         return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, get_mode_null(mode));
788 }
789
790 /**
791  * Transforms a Load.
792  *
793  * @return the created ARM Load node
794  */
795 static ir_node *gen_Load(ir_node *node) {
796         ir_node  *block   = be_transform_node(get_nodes_block(node));
797         ir_node  *ptr     = get_Load_ptr(node);
798         ir_node  *new_ptr = be_transform_node(ptr);
799         ir_node  *mem     = get_Load_mem(node);
800         ir_node  *new_mem = be_transform_node(mem);
801         ir_mode  *mode    = get_Load_mode(node);
802         ir_graph *irg     = current_ir_graph;
803         dbg_info *dbg     = get_irn_dbg_info(node);
804
805         if (mode_is_float(mode)) {
806                 env_cg->have_fp_insn = 1;
807                 if (USE_FPA(env_cg->isa))
808                         return new_rd_arm_fpaLdf(dbg, irg, block, new_ptr, new_mem, mode);
809                 else if (USE_VFP(env_cg->isa)) {
810                         assert(mode != mode_E && "IEEE Extended FP not supported");
811                         panic("VFP not supported yet\n");
812                 }
813                 else {
814                         panic("Softfloat not supported yet\n");
815                         return NULL;
816                 }
817         }
818         else {
819                 assert(mode_is_numP(mode) && "unsupported mode for Load");
820
821                 if (mode_is_signed(mode)) {
822                         /* sign extended loads */
823                         switch (get_mode_size_bits(mode)) {
824                         case 8:
825                                 return new_rd_arm_Loadbs(dbg, irg, block, new_ptr, new_mem);
826                         case 16:
827                                 return new_rd_arm_Loadhs(dbg, irg, block, new_ptr, new_mem);
828                         case 32:
829                                 break;
830                         default:
831                                 assert(!"mode size not supported");
832                         }
833                 } else {
834                         /* zero extended loads */
835                         switch (get_mode_size_bits(mode)) {
836                         case 8:
837                                 return new_rd_arm_Loadb(dbg, irg, block, new_ptr, new_mem);
838                         case 16:
839                                 return new_rd_arm_Loadh(dbg, irg, block, new_ptr, new_mem);
840                         case 32:
841                                 break;
842                         default:
843                                 assert(!"mode size not supported");
844                         }
845                 }
846                 return new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
847         }
848 }
849
850 /**
851  * Transforms a Store.
852  *
853  * @return the created ARM Store node
854  */
855 static ir_node *gen_Store(ir_node *node) {
856         ir_node  *block   = be_transform_node(get_nodes_block(node));
857         ir_node  *ptr     = get_Store_ptr(node);
858         ir_node  *new_ptr = be_transform_node(ptr);
859         ir_node  *mem     = get_Store_mem(node);
860         ir_node  *new_mem = be_transform_node(mem);
861         ir_node  *val     = get_Store_value(node);
862         ir_node  *new_val = be_transform_node(val);
863         ir_mode  *mode    = get_irn_mode(val);
864         ir_graph *irg     = current_ir_graph;
865         dbg_info *dbg     = get_irn_dbg_info(node);
866
867         if (mode_is_float(mode)) {
868                 env_cg->have_fp_insn = 1;
869                 if (USE_FPA(env_cg->isa))
870                         return new_rd_arm_fpaStf(dbg, irg, block, new_ptr, new_val, new_mem, mode);
871                 else if (USE_VFP(env_cg->isa)) {
872                         assert(mode != mode_E && "IEEE Extended FP not supported");
873                         assert(0 && "NYI");
874                 }
875         }
876
877         switch (get_mode_size_bits(mode)) {
878         case 8:
879                 return new_rd_arm_Storeb(dbg, irg, block, new_ptr, new_val, new_mem);
880         case 16:
881                 return new_rd_arm_Storeh(dbg, irg, block, new_ptr, new_val, new_mem);
882         default:
883                 return new_rd_arm_Store(dbg, irg, block, new_ptr, new_val, new_mem);
884         }
885 }
886
887 /**
888  * Transforms a Cond.
889  *
890  * @return the created ARM Cond node
891  */
892 static ir_node *gen_Cond(ir_node *node) {
893         ir_node  *block    = be_transform_node(get_nodes_block(node));
894         ir_node  *selector = get_Cond_selector(node);
895         ir_graph *irg      = current_ir_graph;
896         dbg_info *dbg      = get_irn_dbg_info(node);
897         ir_mode  *mode     = get_irn_mode(selector);
898
899         if (mode == mode_b) {
900                 /* CondJmp */
901                 ir_node *cmp_node = get_Proj_pred(selector);
902                 ir_node *op1      = get_Cmp_left(cmp_node);
903                 ir_node *new_op1  = be_transform_node(op1);
904                 ir_node *op2      = get_Cmp_right(cmp_node);
905                 ir_node *new_op2  = be_transform_node(op2);
906
907                 return new_rd_arm_CondJmp(dbg, irg, block, new_op1, new_op2, get_Proj_proj(selector));
908         } else {
909                 /* SwitchJmp */
910                 ir_node *new_op = be_transform_node(selector);
911                 ir_node *const_graph;
912                 ir_node *sub;
913
914                 ir_node *proj;
915                 const ir_edge_t *edge;
916                 int min = INT_MAX;
917                 int max = INT_MIN;
918                 int translation;
919                 int pn;
920                 int n_projs;
921
922                 foreach_out_edge(node, edge) {
923                         proj = get_edge_src_irn(edge);
924                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
925
926                         pn = get_Proj_proj(proj);
927
928                         min = pn<min ? pn : min;
929                         max = pn>max ? pn : max;
930                 }
931                 translation = min;
932                 n_projs = max - translation + 1;
933
934                 foreach_out_edge(node, edge) {
935                         proj = get_edge_src_irn(edge);
936                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
937
938                         pn = get_Proj_proj(proj) - translation;
939                         set_Proj_proj(proj, pn);
940                 }
941
942
943                 const_graph = create_const_graph_value(env_cg->birg->abi, node, block, translation);
944                 sub = new_rd_arm_Sub(dbg, irg, block, new_op, const_graph, mode, ARM_SHF_NONE, NULL);
945                 return new_rd_arm_SwitchJmp(dbg, irg, block, sub, n_projs, get_Cond_defaultProj(node) - translation);
946         }
947 }
948
949 /**
950  * Returns the name of a SymConst.
951  * @param symc  the SymConst
952  * @return name of the SymConst
953  */
954 static ident *get_sc_ident(ir_node *symc) {
955         ir_entity *ent;
956
957         switch (get_SymConst_kind(symc)) {
958                 case symconst_addr_name:
959                         return get_SymConst_name(symc);
960
961                 case symconst_addr_ent:
962                         ent = get_SymConst_entity(symc);
963                         mark_entity_visited(ent);
964                         return get_entity_ld_ident(ent);
965
966                 default:
967                         assert(0 && "Unsupported SymConst");
968         }
969
970         return NULL;
971 }
972
973 /**
974  * Transforms a Const node.
975  *
976  * @return The transformed ARM node.
977  */
978 static ir_node *gen_Const(ir_node *node) {
979         ir_node  *block = be_transform_node(get_nodes_block(node));
980         ir_mode  *mode  = get_irn_mode(node);
981         dbg_info *dbg   = get_irn_dbg_info(node);
982
983         return create_const_graph(env_cg->birg->abi, node, block);
984 }
985
986
987 /**
988  * Transforms a SymConst node.
989  *
990  * @return The transformed ARM node.
991  */
992 static ir_node *gen_SymConst(ir_node *node) {
993         ir_node  *block = be_transform_node(get_nodes_block(node));
994         ir_mode  *mode  = get_irn_mode(node);
995         dbg_info *dbg   = get_irn_dbg_info(node);
996         ir_node  *res;
997
998         res = new_rd_arm_SymConst(dbg, current_ir_graph, block, mode, get_sc_ident(node));
999         add_irn_dep(res, be_abi_get_start_barrier(env_cg->birg->abi));
1000         /* ensure the const is schedules AFTER the barrier */
1001         return res;
1002 }
1003
1004 /**
1005  * Transforms a CopyB node.
1006  *
1007  * @return The transformed ARM node.
1008  */
1009 static ir_node *gen_CopyB(ir_node *node) {
1010         ir_node  *block    = be_transform_node(get_nodes_block(node));
1011         ir_node  *src      = get_CopyB_src(node);
1012         ir_node  *new_src  = be_transform_node(src);
1013         ir_node  *dst      = get_CopyB_dst(node);
1014         ir_node  *new_dst  = be_transform_node(dst);
1015         ir_node  *mem      = get_CopyB_mem(node);
1016         ir_node  *new_mem  = be_transform_node(mem);
1017         ir_graph *irg      = current_ir_graph;
1018         dbg_info *dbg      = get_irn_dbg_info(node);
1019         int      size      = get_type_size_bytes(get_CopyB_type(node));
1020         ir_node  *src_copy;
1021         ir_node  *dst_copy;
1022
1023         src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, new_src);
1024         dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, new_dst);
1025
1026         return new_rd_arm_CopyB(dbg, irg, block, dst_copy, src_copy,
1027                         new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu),
1028                         new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu),
1029                         new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu),
1030                         mem, new_tarval_from_long(size, mode_Iu));
1031 }
1032
1033
1034 /********************************************
1035  *  _                          _
1036  * | |                        | |
1037  * | |__   ___ _ __   ___   __| | ___  ___
1038  * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
1039  * | |_) |  __/ | | | (_) | (_| |  __/\__ \
1040  * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
1041  *
1042  ********************************************/
1043
1044 /**
1045  * Return an expanding stack offset.
1046  * Note that function is called in the transform phase
1047  * where the stack offsets are still relative regarding
1048  * the first (frame allocating) IncSP.
1049  * However this is exactly what we want because frame
1050  * access must be done relative the the fist IncSP ...
1051  */
1052 static int get_sp_expand_offset(ir_node *inc_sp) {
1053         int offset = be_get_IncSP_offset(inc_sp);
1054
1055         if (offset == BE_STACK_FRAME_SIZE_EXPAND)
1056                 return 0;
1057
1058         return offset;
1059 }
1060
1061 #if 0
1062 static ir_node *gen_StackParam(ir_node *irn) {
1063         ir_node  *block    = be_transform_node(get_nodes_block(node));
1064         ir_node   *new_op = NULL;
1065         ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
1066         ir_node   *mem    = new_rd_NoMem(env->irg);
1067         ir_node   *ptr    = get_irn_n(irn, 0);
1068         ir_entity *ent    = be_get_frame_entity(irn);
1069         ir_mode   *mode   = env->mode;
1070
1071 //      /* If the StackParam has only one user ->     */
1072 //      /* put it in the Block where the user resides */
1073 //      if (get_irn_n_edges(node) == 1) {
1074 //              env->block = get_nodes_block(get_edge_src_irn(get_irn_out_edge_first(node)));
1075 //      }
1076
1077         if (mode_is_float(mode)) {
1078                 if (USE_SSE2(env->cg))
1079                         new_op = new_rd_ia32_fLoad(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1080                 else {
1081                         env->cg->used_x87 = 1;
1082                         new_op = new_rd_ia32_vfld(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1083                 }
1084         }
1085         else {
1086                 new_op = new_rd_ia32_Load(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1087         }
1088
1089         set_ia32_frame_ent(new_op, ent);
1090         set_ia32_use_frame(new_op);
1091
1092         set_ia32_am_support(new_op, ia32_am_Source);
1093         set_ia32_op_type(new_op, ia32_AddrModeS);
1094         set_ia32_am_flavour(new_op, ia32_B);
1095         set_ia32_ls_mode(new_op, mode);
1096
1097         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1098
1099         return new_rd_Proj(env->dbg, env->irg, block, new_op, mode, 0);
1100 }
1101 #endif
1102
1103 /**
1104  * Transforms a FrameAddr into an ARM Add.
1105  */
1106 static ir_node *gen_be_FrameAddr(ir_node *node) {
1107         ir_node   *block  = be_transform_node(get_nodes_block(node));
1108         ir_entity *ent    = be_get_frame_entity(node);
1109         int       offset  = get_entity_offset(ent);
1110         ir_node   *op     = be_get_FrameAddr_frame(node);
1111         ir_node   *new_op = be_transform_node(op);
1112         ir_mode   *mode   = get_irn_mode(node);
1113         dbg_info  *dbg    = get_irn_dbg_info(node);
1114         ir_node   *cnst;
1115
1116         if (be_is_IncSP(op)) {
1117                 /* BEWARE: we get an offset which is absolute from an offset that
1118                    is relative. Both must be merged */
1119                 offset += get_sp_expand_offset(op);
1120         }
1121         cnst = create_const_graph_value(env_cg->birg->abi, node, block, (unsigned)offset);
1122         if (is_arm_Mov_i(cnst))
1123                 return new_rd_arm_Add_i(dbg, current_ir_graph, block, new_op, mode, get_arm_value(cnst));
1124         return new_rd_arm_Add(dbg, current_ir_graph, block, new_op, cnst, mode, ARM_SHF_NONE, NULL);
1125 }
1126
1127 #if 0
1128 /**
1129  * Transforms a FrameLoad into an ARM Load.
1130  */
1131 static ir_node *gen_FrameLoad(ir_node *irn) {
1132         ir_node   *new_op = NULL;
1133         ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
1134         ir_node   *mem    = get_irn_n(irn, 0);
1135         ir_node   *ptr    = get_irn_n(irn, 1);
1136         ir_entity *ent    = be_get_frame_entity(irn);
1137         ir_mode   *mode   = get_type_mode(get_entity_type(ent));
1138
1139         if (mode_is_float(mode)) {
1140                 if (USE_SSE2(env->cg))
1141                         new_op = new_rd_ia32_fLoad(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
1142                 else {
1143                         env->cg->used_x87 = 1;
1144                         new_op = new_rd_ia32_vfld(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
1145                 }
1146         }
1147         else {
1148                 new_op = new_rd_ia32_Load(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
1149         }
1150
1151         set_ia32_frame_ent(new_op, ent);
1152         set_ia32_use_frame(new_op);
1153
1154         set_ia32_am_support(new_op, ia32_am_Source);
1155         set_ia32_op_type(new_op, ia32_AddrModeS);
1156         set_ia32_am_flavour(new_op, ia32_B);
1157         set_ia32_ls_mode(new_op, mode);
1158
1159         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1160
1161         return new_op;
1162 }
1163 #endif
1164
1165 /**
1166  * Transform a be_AddSP into an arm_AddSP. Eat up const sizes.
1167  */
1168 static ir_node *gen_be_AddSP(ir_node *node) {
1169         ir_node  *block  = be_transform_node(get_nodes_block(node));
1170         ir_node  *sz     = get_irn_n(node, be_pos_AddSP_size);
1171         ir_node  *new_sz = be_transform_node(sz);
1172         ir_node  *sp     = get_irn_n(node, be_pos_AddSP_old_sp);
1173         ir_node  *new_sp = be_transform_node(sp);
1174         ir_graph *irg    = current_ir_graph;
1175         dbg_info *dbgi   = get_irn_dbg_info(node);
1176         ir_node  *nomem  = new_NoMem();
1177         ir_node  *new_op;
1178
1179         /* ARM stack grows in reverse direction, make a SubSP */
1180         new_op = new_rd_arm_SubSP(dbgi, irg, block, new_sp, new_sz, nomem);
1181
1182         return new_op;
1183 }
1184
1185 /**
1186  * Transform a be_SubSP into an arm_SubSP. Eat up const sizes.
1187  */
1188 static ir_node *gen_be_SubSP(ir_node *node) {
1189         ir_node  *block  = be_transform_node(get_nodes_block(node));
1190         ir_node  *sz     = get_irn_n(node, be_pos_SubSP_size);
1191         ir_node  *new_sz = be_transform_node(sz);
1192         ir_node  *sp     = get_irn_n(node, be_pos_SubSP_old_sp);
1193         ir_node  *new_sp = be_transform_node(sp);
1194         ir_graph *irg    = current_ir_graph;
1195         dbg_info *dbgi   = get_irn_dbg_info(node);
1196         ir_node  *nomem  = new_NoMem();
1197         ir_node  *new_op;
1198
1199         /* ARM stack grows in reverse direction, make an AddSP */
1200         new_op = new_rd_arm_AddSP(dbgi, irg, block, new_sp, new_sz, nomem);
1201
1202         return new_op;
1203 }
1204
1205 /**
1206  * Transform a be_Copy.
1207  */
1208 static ir_node *gen_be_Copy(ir_node *node) {
1209         ir_node *result = be_duplicate_node(node);
1210         ir_mode *mode   = get_irn_mode(result);
1211
1212         if (mode_needs_gp_reg(mode)) {
1213                 set_irn_mode(node, mode_Iu);
1214         }
1215
1216         return result;
1217 }
1218
1219 /**
1220  * Transform a Proj from a Load.
1221  */
1222 static ir_node *gen_Proj_Load(ir_node *node) {
1223         ir_node  *block    = be_transform_node(get_nodes_block(node));
1224         ir_node  *load     = get_Proj_pred(node);
1225         ir_node  *new_load = be_transform_node(load);
1226         ir_graph *irg      = current_ir_graph;
1227         dbg_info *dbgi     = get_irn_dbg_info(node);
1228         long     proj      = get_Proj_proj(node);
1229
1230         /* renumber the proj */
1231         switch (get_arm_irn_opcode(new_load)) {
1232         case iro_arm_Load:
1233         case iro_arm_Loadb:
1234         case iro_arm_Loadbs:
1235         case iro_arm_Loadh:
1236         case iro_arm_Loadhs:
1237                 /* handle all gp loads equal: they have the same proj numbers. */
1238                 if (proj == pn_Load_res) {
1239                         return new_rd_Proj(dbgi, irg, block, new_load, mode_Iu, pn_arm_Load_res);
1240                 } else if (proj == pn_Load_M) {
1241                         return new_rd_Proj(dbgi, irg, block, new_load, mode_M, pn_arm_Load_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, irg, block, new_load, mode, pn_arm_fpaLdf_res);
1248                 } else if (proj == pn_Load_M) {
1249                         return new_rd_Proj(dbgi, irg, block, new_load, mode_M, pn_arm_fpaLdf_M);
1250                 }
1251                 break;
1252         default:
1253                 break;
1254         }
1255         assert(0);
1256         return new_rd_Unknown(irg, get_irn_mode(node));
1257 }
1258
1259 /**
1260  * Transform and renumber the Projs from a CopyB.
1261  */
1262 static ir_node *gen_Proj_CopyB(ir_node *node) {
1263         ir_node  *block    = be_transform_node(get_nodes_block(node));
1264         ir_node  *pred     = get_Proj_pred(node);
1265         ir_node  *new_pred = be_transform_node(pred);
1266         ir_graph *irg      = current_ir_graph;
1267         dbg_info *dbgi     = get_irn_dbg_info(node);
1268         ir_mode  *mode     = get_irn_mode(node);
1269         long     proj      = get_Proj_proj(node);
1270
1271         switch(proj) {
1272         case pn_CopyB_M_regular:
1273                 if (is_arm_CopyB(new_pred)) {
1274                         return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_CopyB_M);
1275                 }
1276                 break;
1277         default:
1278                 break;
1279         }
1280         assert(0);
1281         return new_rd_Unknown(irg, mode);
1282 }
1283
1284 /**
1285  * Transform and renumber the Projs from a Quot.
1286  */
1287 static ir_node *gen_Proj_Quot(ir_node *node) {
1288         ir_node  *block    = be_transform_node(get_nodes_block(node));
1289         ir_node  *pred     = get_Proj_pred(node);
1290         ir_node  *new_pred = be_transform_node(pred);
1291         ir_graph *irg      = current_ir_graph;
1292         dbg_info *dbgi     = get_irn_dbg_info(node);
1293         ir_mode  *mode     = get_irn_mode(node);
1294         long     proj      = get_Proj_proj(node);
1295
1296         switch (proj) {
1297         case pn_Quot_M:
1298                 if (is_arm_fpaDiv(new_pred)) {
1299                         return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaDiv_M);
1300                 } else if (is_arm_fpaRdv(new_pred)) {
1301                         return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaRdv_M);
1302                 } else if (is_arm_fpaFDiv(new_pred)) {
1303                         return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFDiv_M);
1304                 } else if (is_arm_fpaFRdv(new_pred)) {
1305                         return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFRdv_M);
1306                 }
1307                 break;
1308         case pn_Quot_res:
1309                 if (is_arm_fpaDiv(new_pred)) {
1310                         return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaDiv_res);
1311                 } else if (is_arm_fpaFDiv(new_pred)) {
1312                         return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaRdv_res);
1313                 } else if (is_arm_fpaFDiv(new_pred)) {
1314                         return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFDiv_res);
1315                 } else if (is_arm_fpaFDiv(new_pred)) {
1316                         return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFRdv_res);
1317                 }
1318                 break;
1319         default:
1320                 break;
1321         }
1322         assert(0);
1323         return new_rd_Unknown(irg, mode);
1324 }
1325
1326 /**
1327  * Transform the Projs of an AddSP.
1328  */
1329 static ir_node *gen_Proj_be_AddSP(ir_node *node) {
1330         ir_node  *block    = be_transform_node(get_nodes_block(node));
1331         ir_node  *pred     = get_Proj_pred(node);
1332         ir_node  *new_pred = be_transform_node(pred);
1333         ir_graph *irg      = current_ir_graph;
1334         dbg_info *dbgi     = get_irn_dbg_info(node);
1335         long     proj      = get_Proj_proj(node);
1336
1337         if (proj == pn_be_AddSP_res) {
1338                 ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_arm_AddSP_stack);
1339                 arch_set_irn_register(env_cg->arch_env, res, &arm_gp_regs[REG_SP]);
1340                 return res;
1341         } else if (proj == pn_be_AddSP_M) {
1342                 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_AddSP_M);
1343         }
1344
1345         assert(0);
1346         return new_rd_Unknown(irg, get_irn_mode(node));
1347 }
1348
1349 /**
1350  * Transform the Projs of a SubSP.
1351  */
1352 static ir_node *gen_Proj_be_SubSP(ir_node *node) {
1353         ir_node  *block    = be_transform_node(get_nodes_block(node));
1354         ir_node  *pred     = get_Proj_pred(node);
1355         ir_node  *new_pred = be_transform_node(pred);
1356         ir_graph *irg      = current_ir_graph;
1357         dbg_info *dbgi     = get_irn_dbg_info(node);
1358         long     proj      = get_Proj_proj(node);
1359
1360         if (proj == pn_be_SubSP_res) {
1361                 ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_arm_SubSP_stack);
1362                 arch_set_irn_register(env_cg->arch_env, res, &arm_gp_regs[REG_SP]);
1363                 return res;
1364         } else if (proj == pn_be_SubSP_M) {
1365                 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_SubSP_M);
1366         }
1367
1368         assert(0);
1369         return new_rd_Unknown(irg, get_irn_mode(node));
1370 }
1371
1372 /**
1373  * Transform the Projs from a Cmp.
1374  */
1375 static ir_node *gen_Proj_Cmp(ir_node *node) {
1376         panic("Psi NYI\n");
1377 }
1378
1379
1380 /**
1381  * Transform the Thread Local Storage Proj.
1382  */
1383 static ir_node *gen_Proj_tls(ir_node *node) {
1384         ir_node  *block = be_transform_node(get_nodes_block(node));
1385         ir_graph *irg   = current_ir_graph;
1386         dbg_info *dbgi  = NULL;
1387
1388         return new_rd_arm_LdTls(dbgi, irg, block, mode_Iu);
1389 }
1390
1391 /**
1392  * Transform a Proj node.
1393  */
1394 static ir_node *gen_Proj(ir_node *node) {
1395         ir_graph *irg  = current_ir_graph;
1396         dbg_info *dbgi = get_irn_dbg_info(node);
1397         ir_node  *pred = get_Proj_pred(node);
1398         long     proj  = get_Proj_proj(node);
1399
1400         if (is_Store(pred) || be_is_FrameStore(pred)) {
1401                 if (proj == pn_Store_M) {
1402                         return be_transform_node(pred);
1403                 } else {
1404                         assert(0);
1405                         return new_r_Bad(irg);
1406                 }
1407         } else if (is_Load(pred) || be_is_FrameLoad(pred)) {
1408                 return gen_Proj_Load(node);
1409         } else if (is_CopyB(pred)) {
1410                 return gen_Proj_CopyB(node);
1411         } else if (is_Quot(pred)) {
1412                 return gen_Proj_Quot(node);
1413         } else if (be_is_SubSP(pred)) {
1414                 return gen_Proj_be_SubSP(node);
1415         } else if (be_is_AddSP(pred)) {
1416                 return gen_Proj_be_AddSP(node);
1417         } else if (is_Cmp(pred)) {
1418                 return gen_Proj_Cmp(node);
1419         } else if (get_irn_op(pred) == op_Start) {
1420                 if (proj == pn_Start_X_initial_exec) {
1421                         ir_node *block = get_nodes_block(pred);
1422                         ir_node *jump;
1423
1424                         /* we exchange the ProjX with a jump */
1425                         block = be_transform_node(block);
1426                         jump  = new_rd_Jmp(dbgi, irg, block);
1427                         ir_fprintf(stderr, "created jump: %+F\n", jump);
1428                         return jump;
1429                 }
1430                 if (node == be_get_old_anchor(anchor_tls)) {
1431                         return gen_Proj_tls(node);
1432                 }
1433         } else {
1434                 ir_node *new_pred = be_transform_node(pred);
1435                 ir_node *block    = be_transform_node(get_nodes_block(node));
1436                 ir_mode *mode     = get_irn_mode(node);
1437                 if (mode_needs_gp_reg(mode)) {
1438                         ir_node *new_proj = new_r_Proj(irg, block, new_pred, mode_Iu,
1439                                                        get_Proj_proj(node));
1440 #ifdef DEBUG_libfirm
1441                         new_proj->node_nr = node->node_nr;
1442 #endif
1443                         return new_proj;
1444                 }
1445         }
1446
1447         return be_duplicate_node(node);
1448 }
1449
1450 /**
1451  * Change some phi modes
1452  */
1453 static ir_node *gen_Phi(ir_node *node) {
1454         ir_node  *block = be_transform_node(get_nodes_block(node));
1455         ir_graph *irg   = current_ir_graph;
1456         dbg_info *dbgi  = get_irn_dbg_info(node);
1457         ir_mode  *mode  = get_irn_mode(node);
1458         ir_node  *phi;
1459
1460         if (mode_needs_gp_reg(mode)) {
1461                 /* we shouldn't have any 64bit stuff around anymore */
1462                 assert(get_mode_size_bits(mode) <= 32);
1463                 /* all integer operations are on 32bit registers now */
1464                 mode = mode_Iu;
1465         }
1466
1467         /* phi nodes allow loops, so we use the old arguments for now
1468          * and fix this later */
1469         phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node), get_irn_in(node) + 1);
1470         copy_node_attr(node, phi);
1471         be_duplicate_deps(node, phi);
1472
1473         be_set_transformed_node(node, phi);
1474         be_enqueue_preds(node);
1475
1476         return phi;
1477 }
1478
1479 /*********************************************************
1480  *                  _             _      _
1481  *                 (_)           | |    (_)
1482  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
1483  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
1484  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
1485  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
1486  *
1487  *********************************************************/
1488
1489 /**
1490  * the BAD transformer.
1491  */
1492 static ir_node *bad_transform(ir_node *irn) {
1493         panic("ARM backend: Not implemented: %+F\n", irn);
1494         return irn;
1495 }
1496
1497 /**
1498  * Set a node emitter. Make it a bit more type safe.
1499  */
1500 static INLINE void set_transformer(ir_op *op, be_transform_func arm_transform_func) {
1501         op->ops.generic = (op_func)arm_transform_func;
1502 }
1503
1504 /**
1505  * Enters all transform functions into the generic pointer
1506  */
1507 static void arm_register_transformers(void) {
1508         ir_op *op_Max, *op_Min, *op_Mulh;
1509
1510         /* first clear the generic function pointer for all ops */
1511         clear_irp_opcodes_generic_func();
1512
1513 #define GEN(a)     set_transformer(op_##a, gen_##a)
1514 #define BAD(a)     set_transformer(op_##a, bad_transform)
1515 #define IGN(a)
1516
1517         GEN(Add);
1518         GEN(Sub);
1519         GEN(Mul);
1520         GEN(And);
1521         GEN(Or);
1522         GEN(Eor);
1523
1524         GEN(Shl);
1525         GEN(Shr);
1526         GEN(Shrs);
1527         BAD(Rot);       /* unsupported yet */
1528
1529         GEN(Quot);
1530
1531         /* should be lowered */
1532         BAD(Div);
1533         BAD(Mod);
1534         BAD(DivMod);
1535
1536         GEN(Minus);
1537         GEN(Conv);
1538         GEN(Abs);
1539         GEN(Not);
1540
1541         GEN(Load);
1542         GEN(Store);
1543         GEN(Cond);
1544
1545         BAD(ASM);       /* unsupported yet */
1546         GEN(CopyB);
1547         BAD(Mux);
1548         BAD(Psi);       /* unsupported yet */
1549         GEN(Proj);
1550         GEN(Phi);
1551
1552         IGN(Block);
1553         IGN(End);
1554
1555         GEN(Const);
1556         GEN(SymConst);
1557
1558         /* we should never see these nodes */
1559         BAD(Raise);
1560         BAD(Sel);
1561         BAD(InstOf);
1562         BAD(Cast);
1563         BAD(Free);
1564         BAD(Tuple);
1565         BAD(Id);
1566         //BAD(Bad);
1567         BAD(Confirm);
1568         BAD(Filter);
1569         BAD(CallBegin);
1570         BAD(EndReg);
1571         BAD(EndExcept);
1572
1573         /* handle generic backend nodes */
1574         GEN(be_FrameAddr);
1575         //GEN(be_Call);
1576         //GEN(be_Return);
1577         BAD(be_FrameLoad);      /* unsupported yet */
1578         BAD(be_FrameStore);     /* unsupported yet */
1579         BAD(be_StackParam);     /* unsupported yet */
1580         GEN(be_AddSP);
1581         GEN(be_SubSP);
1582         GEN(be_Copy);
1583
1584         /* set the register for all Unknown nodes */
1585         BAD(Unknown);
1586
1587         op_Max = get_op_Max();
1588         if (op_Max)
1589                 BAD(Max);       /* unsupported yet */
1590         op_Min = get_op_Min();
1591         if (op_Min)
1592                 BAD(Min);       /* unsupported yet */
1593         op_Mulh = get_op_Mulh();
1594         if (op_Mulh)
1595                 BAD(Mulh);      /* unsupported yet */
1596
1597 #undef IGN
1598 #undef GEN
1599 #undef BAD
1600 }
1601
1602 /**
1603  * Pre-transform all unknown and noreg nodes.
1604  */
1605 static void arm_pretransform_node(void *arch_cg) {
1606         arm_code_gen_t *cg = arch_cg;
1607 }
1608
1609 /**
1610  * Transform a Firm graph into an ARM graph.
1611  */
1612 void arm_transform_graph(arm_code_gen_t *cg) {
1613         arm_register_transformers();
1614         env_cg = cg;
1615         be_transform_graph(cg->birg, /*arm_pretransform_node*/ NULL, cg);
1616 }
1617
1618 void arm_init_transform(void) {
1619         // FIRM_DBG_REGISTER(dbg, "firm.be.arm.transform");
1620 }