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