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