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