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