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