fpa constants implemented
[libfirm] / ir / be / arm / arm_transform.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   The codegenerator (transform FIRM into arm FIRM)
23  * @author  Oliver Richter, Tobias Gneist, Michael Beck
24  * @version $Id$
25  */
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "irnode_t.h"
31 #include "irgraph_t.h"
32 #include "irmode_t.h"
33 #include "irgmod.h"
34 #include "iredges.h"
35 #include "irvrfy.h"
36 #include "ircons.h"
37 #include "irprintf.h"
38 #include "dbginfo.h"
39 #include "iropt_t.h"
40 #include "debug.h"
41
42 #include "../benode_t.h"
43 #include "../beirg_t.h"
44 #include "bearch_arm_t.h"
45
46 #include "arm_nodes_attr.h"
47 #include "archop.h"
48 #include "arm_transform.h"
49 #include "arm_new_nodes.h"
50 #include "arm_map_regs.h"
51
52 #include "gen_arm_regalloc_if.h"
53
54 #include <limits.h>
55
56
57 extern ir_op *get_op_Mulh(void);
58
59
60
61 /****************************************************************************************************
62  *                  _        _                        __                           _   _
63  *                 | |      | |                      / _|                         | | (_)
64  *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
65  * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
66  * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
67  * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
68  *
69  ****************************************************************************************************/
70
71 typedef struct vals_ {
72         int ops;
73         unsigned char values[4];
74         unsigned char shifts[4];
75 } vals;
76
77 /** Execute ROL. */
78 static unsigned do_rol(unsigned v, unsigned rol) {
79         return (v << rol) | (v >> (32 - rol));
80 }
81
82 /**
83  * construct 8bit values und rot amounts for a value
84  */
85 static void gen_vals_from_word(unsigned int value, vals *result)
86 {
87         int initial = 0;
88
89         memset(result, 0, sizeof(*result));
90
91         /* special case: we prefer shift amount 0 */
92         if (value < 0x100) {
93                 result->values[0] = value;
94                 result->ops       = 1;
95                 return;
96         }
97
98         while (value != 0) {
99                 if (value & 0xFF) {
100                         unsigned v = do_rol(value, 8) & 0xFFFFFF;
101                         int shf = 0;
102                         for (;;) {
103                                 if ((v & 3) != 0)
104                                         break;
105                                 shf += 2;
106                                 v >>= 2;
107                         }
108                         v  &= 0xFF;
109                         shf = (initial + shf - 8) & 0x1F;
110                         result->values[result->ops] = v;
111                         result->shifts[result->ops] = shf;
112                         ++result->ops;
113
114                         value ^= do_rol(v, shf) >> initial;
115                 }
116                 else {
117                         value >>= 8;
118                         initial += 8;
119                 }
120         }
121 }
122
123 /**
124  * Creates a arm_Const node.
125  */
126 static ir_node *create_const_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) {
127         tarval *tv = new_tarval_from_long(value, mode_Iu);
128         dbg_info *dbg = get_irn_dbg_info(irn);
129         ir_node *res = new_rd_arm_Mov_i(dbg, current_ir_graph, block, get_irn_mode(irn), tv);
130         /* ensure the const is schedules AFTER the barrier */
131         add_irn_dep(res, be_abi_get_start_barrier(abi));
132         return res;
133 }
134
135 /**
136  * Creates a arm_Const_Neg node.
137  */
138 static ir_node *create_const_neg_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) {
139         tarval *tv = new_tarval_from_long(value, mode_Iu);
140         dbg_info *dbg = get_irn_dbg_info(irn);
141         ir_node *res = new_rd_arm_Mvn_i(dbg, current_ir_graph, block, get_irn_mode(irn), tv);
142         add_irn_dep(res, be_abi_get_start_barrier(abi));
143         /* ensure the const is schedules AFTER the barrier */
144         return res;
145 }
146
147 #define NEW_BINOP_NODE(opname, env, op1, op2) new_rd_arm_##opname(env->dbg, current_ir_graph, env->block, op1, op2, env->mode)
148
149 /**
150  * Encodes an immediate with shifter operand
151  */
152 static unsigned int arm_encode_imm_w_shift(unsigned int shift, unsigned int immediate) {
153         return immediate | ((shift>>1)<<8);
154 }
155
156 /**
157  * Decode an immediate with shifter operand
158  */
159 unsigned int arm_decode_imm_w_shift(tarval *tv) {
160         unsigned l = get_tarval_long(tv);
161         unsigned rol = (l & ~0xFF) >> 7;
162
163         return do_rol(l & 0xFF, rol);
164 }
165
166 /**
167  * Creates a possible DAG for an constant.
168  */
169 static ir_node *create_const_graph_value(be_abi_irg_t *abi, ir_node *irn, ir_node *block, unsigned int value) {
170         ir_node *result;
171         vals v, vn;
172         int cnt;
173         ir_mode *mode = get_irn_mode(irn);
174         dbg_info *dbg = get_irn_dbg_info(irn);
175
176         gen_vals_from_word(value, &v);
177         gen_vals_from_word(~value, &vn);
178
179         if (vn.ops < v.ops) {
180                 /* remove bits */
181                 result = create_const_neg_node(abi, irn, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
182
183                 for (cnt = 1; cnt < vn.ops; ++cnt) {
184                         tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]), mode_Iu);
185                         ir_node *bic_i_node = new_rd_arm_Bic_i(dbg, current_ir_graph, block, result, mode, tv);
186                         result = bic_i_node;
187                 }
188         }
189         else {
190                 /* add bits */
191                 result = create_const_node(abi, irn, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
192
193                 for (cnt = 1; cnt < v.ops; ++cnt) {
194                         tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]), mode_Iu);
195                         ir_node *orr_i_node = new_rd_arm_Or_i(dbg, current_ir_graph, block, result, mode, tv);
196                         result = orr_i_node;
197                 }
198         }
199         return result;
200 }
201
202 /**
203  * Create a DAG constructing a given Const.
204  *
205  * @param irn  a Firm const
206  */
207 static ir_node *create_const_graph(be_abi_irg_t *abi, ir_node *irn, ir_node *block) {
208         int value = get_tarval_long(get_Const_tarval(irn));
209         return create_const_graph_value(abi, irn, block, value);
210 }
211
212 /**
213  * Creates code for a Firm Const node.
214  */
215 static ir_node *gen_arm_Const(ir_node *irn, ir_node *block, arm_code_gen_t *cg) {
216         ir_graph *irg = current_ir_graph;
217         ir_mode *mode = get_irn_mode(irn);
218         dbg_info *dbg = get_irn_dbg_info(irn);
219
220         if (mode_is_float(mode)) {
221                 cg->have_fp = 1;
222                 if (USE_FPA(cg->isa)) {
223                         irn = new_rd_arm_fpaConst(dbg, irg, block, get_Const_tarval(irn));
224                         /* ensure the const is schedules AFTER the barrier */
225                         add_irn_dep(irn, be_abi_get_start_barrier(cg->birg->abi));
226                         return irn;
227                 }
228                 else if (USE_VFP(cg->isa))
229                         assert(mode != mode_E && "IEEE Extended FP not supported");
230                 assert(0 && "NYI");
231         }
232         else if (mode_is_reference(mode))
233                 return irn;
234         return create_const_graph(cg->birg->abi, irn, block);
235 }
236
237 static ir_node *gen_mask(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) {
238         ir_node *block = get_nodes_block(irn);
239         unsigned mask_bits = (1 << result_bits) - 1;
240         ir_node *mask_node = create_const_graph_value(abi, irn, block, mask_bits);
241         dbg_info *dbg = get_irn_dbg_info(irn);
242         return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, get_irn_mode(irn), ARM_SHF_NONE, NULL);
243 }
244
245 static ir_node *gen_sign_extension(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) {
246         ir_node *block = get_nodes_block(irn);
247         int shift_width = 32 - result_bits;
248         ir_graph *irg = current_ir_graph;
249         ir_node *shift_const_node = create_const_graph_value(abi, irn, block, shift_width);
250         dbg_info *dbg = get_irn_dbg_info(irn);
251         ir_node *lshift_node = new_rd_arm_Shl(dbg, irg, block, op, shift_const_node, get_irn_mode(op));
252         ir_node *rshift_node = new_rd_arm_Shrs(dbg, irg, block, lshift_node, shift_const_node, get_irn_mode(irn));
253         return rshift_node;
254 }
255
256 /**
257  * Transforms a Conv node.
258  *
259  * @param env   The transformation environment
260  * @return the created arm Conv node
261  */
262 static ir_node *gen_Conv(ir_node *irn, arm_code_gen_t *cg) {
263         ir_graph *irg = current_ir_graph;
264         ir_node *block   = get_nodes_block(irn);
265         ir_node *op      = get_Conv_op(irn);
266         ir_mode *in_mode = get_irn_mode(op);
267         ir_mode *out_mode = get_irn_mode(irn);
268         dbg_info *dbg    = get_irn_dbg_info(irn);
269
270         if (in_mode == out_mode)
271                 return op;
272
273         if (mode_is_float(in_mode) || mode_is_float(out_mode)) {
274                 cg->have_fp = 1;
275
276                 if (USE_FPA(cg->isa)) {
277                         if (mode_is_float(in_mode)) {
278                                 if (mode_is_float(out_mode)) {
279                                         /* from float to float */
280                                         return new_rd_arm_fpaMov(dbg, irg, block, op, out_mode);
281                                 }
282                                 else {
283                                         /* from float to int */
284                                         return new_rd_arm_fpaFix(dbg, irg, block, op, out_mode);
285                                 }
286                         }
287                         else {
288                                 /* from int to float */
289                                 return new_rd_arm_fpaFlt(dbg, irg, block, op, out_mode);
290                         }
291                 }
292                 assert(0 && "NYI");
293         }
294         else { /* complete in gp registers */
295                 int in_bits  = get_mode_size_bits(in_mode);
296                 int out_bits = get_mode_size_bits(out_mode);
297                 int in_sign  = get_mode_sign(in_mode);
298                 int out_sign = get_mode_sign(out_mode);
299
300                 // 32 -> 32
301                         // NOPpen
302                 if (in_bits == out_bits && in_bits == 32)
303                         return op;
304
305                 // 16 -> 16
306                         // unsigned -> unsigned
307                                 // NOP
308                         // unsigned -> signed
309                                 // sign extension (31:16)=(15)
310                         // signed -> unsigned
311                                 // maskieren (31:16)=0
312                         // signed -> signed
313                                 // NOP
314                 if (in_bits == out_bits && out_bits < 32) {
315                         if (in_sign && !out_sign) {
316                                 return gen_mask(cg->birg->abi, irn, op, out_bits);
317                         } else {
318                                 return gen_sign_extension(cg->birg->abi, irn, op, out_bits);
319                         }
320                 }
321
322                 // 16 -> 32
323                         // unsigned -> unsigned
324                                 // NOP
325                         // unsigned -> signed
326                                 // NOP
327                         // signed -> unsigned
328                                 // sign extension (31:16)=(15)
329                         // signed -> signed
330                                 // sign extension (31:16)=(15)
331                 if (in_bits < out_bits) {
332                         if (in_sign) {
333                                 return gen_sign_extension(cg->birg->abi, irn, op, out_bits);
334                         } else {
335                                 return op;
336                         }
337                 }
338
339                 // 32 -> 16
340                         // unsigned -> unsigned
341                                 // maskieren (31:16)=0
342                         // unsigned -> signed
343                                 // maskieren (31:16)=0
344                         // signed -> unsigned
345                                 // maskieren (31:16)=0
346                         // signed -> signed
347                                 // sign extension (erledigt auch maskieren) (31:16)=(15)
348                 if (in_bits > out_bits) {
349                         if (in_sign && out_sign) {
350                                 return gen_sign_extension(cg->birg->abi, irn, op, out_bits);
351                         } else {
352                                 return gen_mask(cg->birg->abi, irn, op, out_bits);
353                         }
354                 }
355                 assert(0 && "recheck integer conversion logic!");
356                 return irn;
357         }
358         return NULL;
359 }
360
361 /**
362  * Return true if an operand is a shifter operand
363  */
364 static int is_shifter_operand(ir_node *n, arm_shift_modifier *pmod) {
365         arm_shift_modifier mod = ARM_SHF_NONE;
366
367         if (is_arm_Mov(n))
368                 mod = get_arm_shift_modifier(n);
369
370         *pmod = mod;
371         if (mod != ARM_SHF_NONE) {
372                 long v = get_tarval_long(get_arm_value(n));
373                 if (v < 32)
374                         return (int)v;
375         }
376         return 0;
377 }
378
379 /**
380  * Creates an arm Add.
381  *
382  * @param env   The transformation environment
383  * @return the created arm Add node
384  */
385 static ir_node *gen_Add(ir_node *irn, arm_code_gen_t *cg) {
386         ir_node *block = get_nodes_block(irn);
387         ir_node *op1 = get_Add_left(irn);
388         ir_node *op2 = get_Add_right(irn);
389         ir_mode *mode = get_irn_mode(irn);
390         ir_graph *irg = current_ir_graph;
391         ir_node *op3;
392         int v;
393         arm_shift_modifier mod;
394         dbg_info *dbg = get_irn_dbg_info(irn);
395
396         if (mode_is_float(mode)) {
397                 cg->have_fp = 1;
398                 if (USE_FPA(cg->isa))
399                         return new_rd_arm_fpaAdd(dbg, irg, block, op1, op2, mode);
400                 else if (USE_VFP(cg->isa)) {
401                         assert(mode != mode_E && "IEEE Extended FP not supported");
402                 }
403                 assert(0 && "NYI");
404         }
405         if (mode_is_numP(mode)) {
406                 if (is_arm_Mov_i(op1))
407                         return new_rd_arm_Add_i(dbg, irg, block, op2, mode, get_arm_value(op1));
408                 if (is_arm_Mov_i(op2))
409                         return new_rd_arm_Add_i(dbg, irg, block, op1, mode, get_arm_value(op2));
410
411                 /* check for MLA */
412                 if (is_arm_Mul(op1) && get_irn_n_edges(op1) == 1) {
413                         op3 = op2;
414                         op2 = get_irn_n(op1, 1);
415                         op1 = get_irn_n(op1, 0);
416
417                         return new_rd_arm_Mla(dbg, irg, block, op1, op2, op3, mode);
418                 }
419                 if (is_arm_Mul(op2) && get_irn_n_edges(op2) == 1) {
420                         op3 = op1;
421                         op1 = get_irn_n(op2, 0);
422                         op2 = get_irn_n(op2, 1);
423
424                         return new_rd_arm_Mla(dbg, irg, block, op1, op2, op3, mode);
425                 }
426
427                 /* is the first a shifter */
428                 v = is_shifter_operand(op1, &mod);
429                 if (v) {
430                         op1 = get_irn_n(op1, 0);
431                         return new_rd_arm_Add(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu));
432                 }
433                 /* is the second a shifter */
434                 v = is_shifter_operand(op2, &mod);
435                 if (v) {
436                         op2 = get_irn_n(op2, 0);
437                         return new_rd_arm_Add(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu));
438                 }
439
440                 /* normal ADD */
441                 return new_rd_arm_Add(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL);
442         }
443
444         assert(0 && "unknown mode for add");
445         return NULL;
446 }
447
448 /**
449  * Creates an arm Mul.
450  *
451  * @param env   The transformation environment
452  * @return the created arm Mul node
453  */
454 static ir_node *gen_Mul(ir_node *irn, arm_code_gen_t *cg) {
455         ir_node *block = get_nodes_block(irn);
456         ir_node *op1 = get_Mul_left(irn);
457         ir_node *op2 = get_Mul_right(irn);
458         ir_mode *mode = get_irn_mode(irn);
459         ir_graph *irg = current_ir_graph;
460         dbg_info *dbg = get_irn_dbg_info(irn);
461
462         if (mode_is_float(mode)) {
463                 cg->have_fp = 1;
464                 if (USE_FPA(cg->isa))
465                         return new_rd_arm_fpaMul(dbg, irg, block, op1, op2, mode);
466                 else if (USE_VFP(cg->isa)) {
467                         assert(mode != mode_E && "IEEE Extended FP not supported");
468                 }
469                 assert(0 && "NYI");
470         }
471         return new_rd_arm_Mul(dbg, irg, block, op1, op2, mode);
472 }
473
474 /**
475  * Creates an arm floating point Div.
476  *
477  * @param env   The transformation environment
478  * @return the created arm fDiv node
479  */
480 static ir_node *gen_Quot(ir_node *irn, arm_code_gen_t *cg) {
481         ir_node *block = get_nodes_block(irn);
482         ir_node *op1 = get_Quot_left(irn);
483         ir_node *op2 = get_Quot_right(irn);
484         ir_mode *mode = get_irn_mode(irn);
485         dbg_info *dbg = get_irn_dbg_info(irn);
486
487         assert(mode != mode_E && "IEEE Extended FP not supported");
488
489         cg->have_fp = 1;
490         if (USE_FPA(cg->isa))
491                 return new_rd_arm_fpaDiv(dbg, current_ir_graph, block, op1, op2, mode);
492         else if (USE_VFP(cg->isa)) {
493                 assert(mode != mode_E && "IEEE Extended FP not supported");
494         }
495         assert(0 && "NYI");
496
497         return NULL;
498 }
499
500 #define GEN_INT_OP(op) \
501 static ir_node *gen_ ## op(ir_node *irn, arm_code_gen_t *cg) { \
502         ir_graph *irg = current_ir_graph; \
503         ir_node *block = get_nodes_block(irn); \
504         ir_node *op1 = get_ ## op ## _left(irn); \
505         ir_node *op2 = get_ ## op ## _right(irn); \
506         int v; \
507         arm_shift_modifier mod; \
508         ir_mode *mode = get_irn_mode(irn); \
509         dbg_info *dbg = get_irn_dbg_info(irn); \
510  \
511         if (is_arm_Mov_i(op1)) \
512                 return new_rd_arm_ ## op ## _i(dbg, irg, block, op2, mode, get_arm_value(op1)); \
513         if (is_arm_Mov_i(op2)) \
514                 return new_rd_arm_ ## op ## _i(dbg, irg, block, op1, mode, get_arm_value(op2)); \
515         /* is the first a shifter */ \
516         v = is_shifter_operand(op1, &mod); \
517         if (v) { \
518                 op1 = get_irn_n(op1, 0); \
519                 return new_rd_arm_ ## op(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu)); \
520         } \
521         /* is the second a shifter */ \
522         v = is_shifter_operand(op2, &mod); \
523         if (v) { \
524                 op2 = get_irn_n(op2, 0); \
525                 return new_rd_arm_ ## op(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu)); \
526         } \
527         /* Normal op */ \
528         return new_rd_arm_ ## op(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL); \
529 }
530
531
532 /**
533  * Creates an arm And.
534  *
535  * @param env   The transformation environment
536  * @return the created arm And node
537  */
538 static ir_node *gen_And(ir_node *irn, arm_code_gen_t *cg);
539 GEN_INT_OP(And)
540
541 /**
542  * Creates an arm Orr.
543  *
544  * @param env   The transformation environment
545  * @return the created arm Or node
546  */
547 static ir_node *gen_Or(ir_node *irn, arm_code_gen_t *cg);
548 GEN_INT_OP(Or)
549
550 /**
551  * Creates an arm Eor.
552  *
553  * @param env   The transformation environment
554  * @return the created arm Eor node
555  */
556 static ir_node *gen_Eor(ir_node *irn, arm_code_gen_t *cg);
557 GEN_INT_OP(Eor)
558
559 /**
560  * Creates an arm Sub.
561  *
562  * @param env   The transformation environment
563  * @return the created arm Sub node
564  */
565 static ir_node *gen_Sub(ir_node *irn, arm_code_gen_t *cg) {
566         ir_node *block = get_nodes_block(irn);
567         ir_node *op1 = get_Sub_left(irn);
568         ir_node *op2 = get_Sub_right(irn);
569         int v;
570         arm_shift_modifier mod;
571         ir_mode *mode = get_irn_mode(irn);
572         ir_graph *irg = current_ir_graph;
573         dbg_info *dbg = get_irn_dbg_info(irn);
574
575         if (mode_is_float(mode)) {
576                 cg->have_fp = 1;
577                 if (USE_FPA(cg->isa))
578                         return new_rd_arm_fpaSub(dbg, irg, block, op1, op2, mode);
579                 else if (USE_VFP(cg->isa)) {
580                         assert(mode != mode_E && "IEEE Extended FP not supported");
581                 }
582                 assert(0 && "NYI");
583         }
584         if (mode_is_numP(mode)) {
585                 if (is_arm_Mov_i(op1))
586                         return new_rd_arm_Rsb_i(dbg, irg, block, op2, mode, get_arm_value(op1));
587                 if (is_arm_Mov_i(op2))
588                         return new_rd_arm_Sub_i(dbg, irg, block, op1, mode, get_arm_value(op2));
589
590                 /* is the first a shifter */
591                 v = is_shifter_operand(op1, &mod);
592                 if (v) {
593                         op1 = get_irn_n(op1, 0);
594                         return new_rd_arm_Rsb(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu));
595                 }
596                 /* is the second a shifter */
597                 v = is_shifter_operand(op2, &mod);
598                 if (v) {
599                         op2 = get_irn_n(op2, 0);
600                         return new_rd_arm_Sub(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu));
601                 }
602                 /* normal sub */
603                 return new_rd_arm_Sub(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL);
604         }
605         assert(0 && "unknown mode for sub");
606         return NULL;
607 }
608
609 /**
610  * Creates an arm Shl.
611  *
612  * @param env   The transformation environment
613  * @return the created arm Shl node
614  */
615 static ir_node *gen_Shl(ir_node *irn, arm_code_gen_t *cg) {
616         ir_node *result;
617         ir_node *block = get_nodes_block(irn);
618         ir_node *op1 = get_Shl_left(irn);
619         ir_node *op2 = get_Shl_right(irn);
620         ir_mode *mode = get_irn_mode(irn);
621         ir_graph *irg = current_ir_graph;
622         dbg_info *dbg = get_irn_dbg_info(irn);
623
624         if (is_arm_Mov_i(op2)) {
625                 result = new_rd_arm_Mov(dbg, irg, block, op1, mode, ARM_SHF_LSL, get_arm_value(op2));
626         } else {
627                 result = new_rd_arm_Shl(dbg, irg, block, op1, op2, mode);
628         }
629         return result;
630 }
631
632 /**
633  * Creates an arm Shr.
634  *
635  * @param env   The transformation environment
636  * @return the created arm Shr node
637  */
638 static ir_node *gen_Shr(ir_node *irn, arm_code_gen_t *cg) {
639         ir_node *result;
640         ir_node *block = get_nodes_block(irn);
641         ir_node *op1 = get_Shr_left(irn);
642         ir_node *op2 = get_Shr_right(irn);
643         ir_mode *mode = get_irn_mode(irn);
644         ir_graph *irg = current_ir_graph;
645         dbg_info *dbg = get_irn_dbg_info(irn);
646
647         if (is_arm_Mov_i(op2)) {
648                 result = new_rd_arm_Mov(dbg, irg, block, op1, mode, ARM_SHF_LSR, get_arm_value(op2));
649         } else {
650                 result = new_rd_arm_Shr(dbg, irg, block, op1, op2, mode);
651         }
652         return result;
653 }
654
655 /**
656  * Creates an arm Shrs.
657  *
658  * @param env   The transformation environment
659  * @return the created arm Shrs node
660  */
661 static ir_node *gen_Shrs(ir_node *irn, arm_code_gen_t *cg) {
662         ir_node *result;
663         ir_node *block = get_nodes_block(irn);
664         ir_node *op1 = get_Shrs_left(irn);
665         ir_node *op2 = get_Shrs_right(irn);
666         ir_mode *mode = get_irn_mode(irn);
667         dbg_info *dbg = get_irn_dbg_info(irn);
668
669         if (is_arm_Mov_i(op2)) {
670                 result = new_rd_arm_Mov(dbg, current_ir_graph, block, op1, mode, ARM_SHF_ASR, get_arm_value(op2));
671         } else {
672                 result = new_rd_arm_Shrs(dbg, current_ir_graph, block, op1, op2, mode);
673         }
674         return result;
675 }
676
677 /**
678  * Transforms a Not node.
679  *
680  * @param env   The transformation environment
681  * @return the created arm Not node
682  */
683 static ir_node *gen_Not(ir_node *irn, arm_code_gen_t *cg) {
684         ir_node *block = get_nodes_block(irn);
685         ir_node *op = get_Not_op(irn);
686         int v;
687         arm_shift_modifier mod = ARM_SHF_NONE;
688         tarval  *tv = NULL;
689         dbg_info *dbg = get_irn_dbg_info(irn);
690
691         v = is_shifter_operand(op, &mod);
692         if (v) {
693                 op = get_irn_n(op, 0);
694                 tv = new_tarval_from_long(v, mode_Iu);
695         }
696         return new_rd_arm_Mvn(dbg, current_ir_graph, block, op, get_irn_mode(irn), mod, tv);
697 }
698
699 /**
700  * Transforms an Abs node.
701  *
702  * @param env   The transformation environment
703  * @return the created arm Abs node
704  */
705 static ir_node *gen_Abs(ir_node *irn, arm_code_gen_t *cg) {
706         ir_node *block = get_nodes_block(irn);
707         ir_node *op = get_Abs_op(irn);
708         ir_mode *mode = get_irn_mode(irn);
709         dbg_info *dbg = get_irn_dbg_info(irn);
710
711         if (mode_is_float(mode)) {
712                 cg->have_fp = 1;
713                 if (USE_FPA(cg->isa))
714                         return new_rd_arm_fpaAbs(dbg, current_ir_graph, block, op, mode);
715                 else if (USE_VFP(cg->isa)) {
716                         assert(mode != mode_E && "IEEE Extended FP not supported");
717                 }
718                 assert(0 && "NYI");
719         }
720         return new_rd_arm_Abs(dbg, current_ir_graph, block, op, mode);
721 }
722
723 /**
724  * Transforms a Minus node.
725  *
726  * @param env   The transformation environment
727  * @return the created arm Minus node
728  */
729 static ir_node *gen_Minus(ir_node *irn, arm_code_gen_t *cg) {
730         ir_node *block = get_nodes_block(irn);
731         ir_node *op = get_Minus_op(irn);
732         ir_mode *mode = get_irn_mode(irn);
733         ir_graph *irg = current_ir_graph;
734         dbg_info *dbg = get_irn_dbg_info(irn);
735
736         if (mode_is_float(mode)) {
737                 cg->have_fp = 1;
738                 if (USE_FPA(cg->isa))
739                         return new_rd_arm_fpaMnv(dbg, irg, block, op, mode);
740                 else if (USE_VFP(cg->isa)) {
741                         assert(mode != mode_E && "IEEE Extended FP not supported");
742                 }
743                 assert(0 && "NYI");
744         }
745         return new_rd_arm_Rsb_i(dbg, irg, block, op, mode, get_mode_null(mode));
746 }
747
748 /**
749  * Transforms a Load.
750  *
751  * @param mod     the debug module
752  * @param block   the block the new node should belong to
753  * @param node    the ir Load node
754  * @param mode    node mode
755  * @return the created arm Load node
756  */
757 static ir_node *gen_Load(ir_node *irn, arm_code_gen_t *cg) {
758         ir_node *block = get_nodes_block(irn);
759         ir_mode *mode = get_Load_mode(irn);
760         ir_graph *irg = current_ir_graph;
761         dbg_info *dbg = get_irn_dbg_info(irn);
762
763         if (mode_is_float(mode)) {
764                 cg->have_fp = 1;
765                 if (USE_FPA(cg->isa))
766                         return new_rd_arm_fpaLdf(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn),
767                                 get_Load_mode(irn));
768                 else if (USE_VFP(cg->isa)) {
769                         assert(mode != mode_E && "IEEE Extended FP not supported");
770                 }
771                 assert(0 && "NYI");
772         }
773         if (mode == mode_Bu) {
774                 return new_rd_arm_Loadb(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
775         }
776         if (mode == mode_Bs) {
777                 return new_rd_arm_Loadbs(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
778         }
779         if (mode == mode_Hu) {
780                 return new_rd_arm_Loadh(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
781         }
782         if (mode == mode_Hs) {
783                 return new_rd_arm_Loadhs(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
784         }
785         if (mode_is_reference(mode)) {
786                 return new_rd_arm_Load(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
787         }
788         return new_rd_arm_Load(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
789 }
790
791 /**
792  * Transforms a Store.
793  *
794  * @param mod     the debug module
795  * @param block   the block the new node should belong to
796  * @param node    the ir Store node
797  * @param mode    node mode
798  * @return the created arm Store node
799  */
800 static ir_node *gen_Store(ir_node *irn, arm_code_gen_t *cg) {
801         ir_node *block = get_nodes_block(irn);
802         ir_mode *mode = get_irn_mode(get_Store_value(irn));
803         ir_graph *irg = current_ir_graph;
804         dbg_info *dbg = get_irn_dbg_info(irn);
805
806         assert(mode != mode_E && "IEEE Extended FP not supported");
807         if (mode_is_float(mode)) {
808                 cg->have_fp = 1;
809                 if (USE_FPA(cg->isa))
810                         return new_rd_arm_fpaStf(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn),
811                                 get_Store_mem(irn), get_irn_mode(get_Store_value(irn)));
812                 else if (USE_VFP(cg->isa)) {
813                         assert(mode != mode_E && "IEEE Extended FP not supported");
814                 }
815                 assert(0 && "NYI");
816         }
817         if (mode == mode_Bu) {
818                 return new_rd_arm_Storeb(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
819         }
820         if (mode == mode_Bs) {
821                 return new_rd_arm_Storebs(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
822         }
823         if (mode == mode_Hu) {
824                 return new_rd_arm_Storeh(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
825         }
826         if (mode == mode_Hs) {
827                 return new_rd_arm_Storehs(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
828         }
829         return new_rd_arm_Store(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
830 }
831
832
833 static ir_node *gen_Cond(ir_node *irn, arm_code_gen_t *cg) {
834         ir_node *result   = NULL;
835         ir_node *selector = get_Cond_selector(irn);
836         ir_node *block    = get_nodes_block(irn);
837         ir_graph *irg     = current_ir_graph;
838         dbg_info *dbg     = get_irn_dbg_info(irn);
839
840         if ( get_irn_mode(selector) == mode_b ) {
841                 //CondJmp
842                 ir_node *proj_node = get_Cond_selector(irn);
843                 ir_node *cmp_node = get_Proj_pred(proj_node);
844                 ir_node *op1 = get_Cmp_left(cmp_node);
845                 ir_node *op2 = get_Cmp_right(cmp_node);
846                 result = new_rd_arm_CondJmp(dbg, irg, block, op1, op2, get_Proj_proj(proj_node));
847         } else {
848                 //SwitchJmp
849                 ir_node *op = get_irn_n(irn, 0);
850                 ir_node *const_graph;
851                 ir_node *sub;
852                 ir_node *const_node;
853
854                 ir_node *proj;
855                 const ir_edge_t *edge;
856                 int min = INT_MAX;
857                 int max = INT_MIN;
858                 int translation;
859                 int norm_max;
860                 int norm_min;
861                 int pn;
862                 int n_projs;
863                 ir_node **projs;
864
865                 foreach_out_edge(irn, edge) {
866                         proj = get_edge_src_irn(edge);
867                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
868
869                         pn = get_Proj_proj(proj);
870
871                         min = pn<min ? pn : min;
872                         max = pn>max ? pn : max;
873                 }
874                 translation = min;
875                 norm_max = max - translation;
876                 norm_min = min - translation;
877
878                 n_projs = norm_max + 1;
879                 projs = xcalloc(n_projs , sizeof(ir_node*));
880
881
882                 foreach_out_edge(irn, edge) {
883                         proj = get_edge_src_irn(edge);
884                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
885
886                         pn = get_Proj_proj(proj) - translation;
887                         set_Proj_proj(proj, pn);
888                 }
889
890
891                 const_node  = new_rd_Const(dbg, irg, block, mode_Iu, new_tarval_from_long(translation, mode_Iu));
892                 const_graph = create_const_graph(cg->birg->abi, const_node, block);
893                 sub = new_rd_arm_Sub(dbg, irg, block, op, const_graph, get_irn_mode(op), ARM_SHF_NONE, NULL);
894                 result = new_rd_arm_SwitchJmp(dbg, irg, block, sub,
895                         n_projs, get_Cond_defaultProj(irn)-translation);
896         }
897         return result;
898 }
899
900 /**
901  * Returns the name of a SymConst.
902  * @param symc  the SymConst
903  * @return name of the SymConst
904  */
905 static ident *get_sc_ident(ir_node *symc) {
906         ir_entity *ent;
907
908         switch (get_SymConst_kind(symc)) {
909                 case symconst_addr_name:
910                         return get_SymConst_name(symc);
911
912                 case symconst_addr_ent:
913                         ent = get_SymConst_entity(symc);
914                         mark_entity_visited(ent);
915                         return get_entity_ld_ident(ent);
916
917                 default:
918                         assert(0 && "Unsupported SymConst");
919         }
920
921         return NULL;
922 }
923
924 /**
925  * Transforms a SymConst node.
926  */
927 static ir_node *gen_SymConst(ir_node *irn, arm_code_gen_t *cg) {
928         ir_node *block = get_nodes_block(irn);
929         ir_mode *mode = get_irn_mode(irn);
930         dbg_info *dbg = get_irn_dbg_info(irn);
931         return new_rd_arm_SymConst(dbg, current_ir_graph, block, mode, get_sc_ident(irn));
932 }
933
934
935
936 /**
937  * Transforms a CopyB node.
938  *
939  * @param env   The transformation environment
940  * @return The transformed node.
941  */
942 static ir_node *gen_CopyB(ir_node *irn, arm_code_gen_t *cg) {
943         ir_node  *res   = NULL;
944         dbg_info *dbg   = get_irn_dbg_info(irn);
945         ir_mode  *mode  = get_irn_mode(irn);
946         ir_node  *src   = get_CopyB_src(irn);
947         ir_node  *dst   = get_CopyB_dst(irn);
948         ir_node  *mem   = get_CopyB_mem(irn);
949         ir_node  *block = get_nodes_block(irn);
950         int       size  = get_type_size_bytes(get_CopyB_type(irn));
951         ir_graph *irg   = current_ir_graph;
952         ir_node *src_copy;
953         ir_node *dst_copy;
954
955         src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, src);
956         dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, dst);
957
958         res = new_rd_arm_CopyB( dbg, irg, block, dst_copy, src_copy, new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), mem, mode);
959         set_arm_value(res, new_tarval_from_long(size, mode_Iu));
960
961         return res;
962 }
963
964
965
966
967
968 /********************************************
969  *  _                          _
970  * | |                        | |
971  * | |__   ___ _ __   ___   __| | ___  ___
972  * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
973  * | |_) |  __/ | | | (_) | (_| |  __/\__ \
974  * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
975  *
976  ********************************************/
977
978 /**
979  * Return an expanding stack offset.
980  * Note that function is called in the transform phase
981  * where the stack offsets are still relative regarding
982  * the first (frame allocating) IncSP.
983  * However this is exactly what we want because frame
984  * access must be done relative the the fist IncSP ...
985  */
986 static int get_sp_expand_offset(ir_node *inc_sp) {
987         int offset = be_get_IncSP_offset(inc_sp);
988
989         if (offset == BE_STACK_FRAME_SIZE_EXPAND)
990                 return 0;
991
992         return offset;
993 }
994
995 #if 0
996 static ir_node *gen_StackParam(ir_node *irn, arm_code_gen_t *cg) {
997         ir_node   *new_op = NULL;
998         ir_node   *block  = get_nodes_block(irn);
999         ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
1000         ir_node   *mem    = new_rd_NoMem(env->irg);
1001         ir_node   *ptr    = get_irn_n(irn, 0);
1002         ir_entity *ent    = be_get_frame_entity(irn);
1003         ir_mode   *mode   = env->mode;
1004
1005 //      /* If the StackParam has only one user ->     */
1006 //      /* put it in the Block where the user resides */
1007 //      if (get_irn_n_edges(node) == 1) {
1008 //              env->block = get_nodes_block(get_edge_src_irn(get_irn_out_edge_first(node)));
1009 //      }
1010
1011         if (mode_is_float(mode)) {
1012                 if (USE_SSE2(env->cg))
1013                         new_op = new_rd_ia32_fLoad(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1014                 else {
1015                         env->cg->used_x87 = 1;
1016                         new_op = new_rd_ia32_vfld(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1017                 }
1018         }
1019         else {
1020                 new_op = new_rd_ia32_Load(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1021         }
1022
1023         set_ia32_frame_ent(new_op, ent);
1024         set_ia32_use_frame(new_op);
1025
1026         set_ia32_am_support(new_op, ia32_am_Source);
1027         set_ia32_op_type(new_op, ia32_AddrModeS);
1028         set_ia32_am_flavour(new_op, ia32_B);
1029         set_ia32_ls_mode(new_op, mode);
1030
1031         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1032
1033         return new_rd_Proj(env->dbg, env->irg, block, new_op, mode, 0);
1034 }
1035 #endif
1036
1037 /**
1038  * Transforms a FrameAddr into an ia32 Add.
1039  */
1040 static ir_node *gen_be_FrameAddr(ir_node *irn, arm_code_gen_t *cg) {
1041         ir_node *block  = get_nodes_block(irn);
1042         ir_entity *ent  = be_get_frame_entity(irn);
1043         int     offset  = get_entity_offset(ent);
1044         ir_node *op     = get_irn_n(irn, 0);
1045         ir_node *cnst;
1046         ir_mode *mode   = get_irn_mode(irn);
1047         dbg_info *dbg   = get_irn_dbg_info(irn);
1048
1049         if (be_is_IncSP(op)) {
1050                 /* BEWARE: we get an offset which is absolute from an offset that
1051                    is relative. Both must be merged */
1052                 offset += get_sp_expand_offset(op);
1053         }
1054         cnst = create_const_graph_value(cg->birg->abi, irn, block, (unsigned)offset);
1055         if (is_arm_Mov_i(cnst))
1056                 return new_rd_arm_Add_i(dbg, current_ir_graph, block, op, mode, get_arm_value(cnst));
1057         return new_rd_arm_Add(dbg, current_ir_graph, block, op, cnst, mode, ARM_SHF_NONE, NULL);
1058 }
1059
1060 #if 0
1061 /**
1062  * Transforms a FrameLoad into an ia32 Load.
1063  */
1064 static ir_node *gen_FrameLoad(ir_node *irn, arm_code_gen_t *cg) {
1065         ir_node   *new_op = NULL;
1066         ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
1067         ir_node   *mem    = get_irn_n(irn, 0);
1068         ir_node   *ptr    = get_irn_n(irn, 1);
1069         ir_entity *ent    = be_get_frame_entity(irn);
1070         ir_mode   *mode   = get_type_mode(get_entity_type(ent));
1071
1072         if (mode_is_float(mode)) {
1073                 if (USE_SSE2(env->cg))
1074                         new_op = new_rd_ia32_fLoad(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
1075                 else {
1076                         env->cg->used_x87 = 1;
1077                         new_op = new_rd_ia32_vfld(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
1078                 }
1079         }
1080         else {
1081                 new_op = new_rd_ia32_Load(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
1082         }
1083
1084         set_ia32_frame_ent(new_op, ent);
1085         set_ia32_use_frame(new_op);
1086
1087         set_ia32_am_support(new_op, ia32_am_Source);
1088         set_ia32_op_type(new_op, ia32_AddrModeS);
1089         set_ia32_am_flavour(new_op, ia32_B);
1090         set_ia32_ls_mode(new_op, mode);
1091
1092         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1093
1094         return new_op;
1095 }
1096 #endif
1097
1098 #if 0
1099 /**
1100  * Transforms a FrameStore into an ia32 Store.
1101  */
1102 static ir_node *gen_FrameStore(ir_node *irn, arm_code_gen_t *cg) {
1103         ir_node   *new_op = NULL;
1104         ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
1105         ir_node   *mem    = get_irn_n(irn, 0);
1106         ir_node   *ptr    = get_irn_n(irn, 1);
1107         ir_node   *val    = get_irn_n(irn, 2);
1108         ir_entity *ent    = be_get_frame_entity(irn);
1109         ir_mode   *mode   = get_irn_mode(val);
1110
1111         if (mode_is_float(mode)) {
1112                 if (USE_SSE2(env->cg))
1113                         new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1114                 else {
1115                         env->cg->used_x87 = 1;
1116                         new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1117                 }
1118         }
1119         else if (get_mode_size_bits(mode) == 8) {
1120                 new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1121         }
1122         else {
1123                 new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1124         }
1125
1126         set_ia32_frame_ent(new_op, ent);
1127         set_ia32_use_frame(new_op);
1128
1129         set_ia32_am_support(new_op, ia32_am_Dest);
1130         set_ia32_op_type(new_op, ia32_AddrModeD);
1131         set_ia32_am_flavour(new_op, ia32_B);
1132         set_ia32_ls_mode(new_op, mode);
1133
1134         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1135
1136         return new_op;
1137 }
1138 #endif
1139
1140
1141 // static ir_node *gen_be_Copy(ir_node *irn, arm_code_gen_t *cg) {
1142 //      return new_rd_arm_Copy(env->dbg, env->irg, env->block, op, env->mode);
1143 // }
1144
1145 /*********************************************************
1146  *                  _             _      _
1147  *                 (_)           | |    (_)
1148  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
1149  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
1150  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
1151  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
1152  *
1153  *********************************************************/
1154
1155 /**
1156  * move constants out of the start block
1157  */
1158 void arm_move_consts(ir_node *node, void *env) {
1159         arm_code_gen_t *cg = env;
1160         int i;
1161
1162         if (is_Block(node))
1163                 return;
1164
1165         if (is_Phi(node)) {
1166                 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
1167                         ir_node *pred = get_irn_n(node,i);
1168                         ir_opcode pred_code = get_irn_opcode(pred);
1169                         if (pred_code == iro_Const) {
1170                                 ir_node *block = get_nodes_block(get_irn_n(get_nodes_block(node),i));
1171                                 ir_node *nn    = gen_arm_Const(pred, block, cg);
1172                                 set_irn_n(node, i, nn);
1173                         }
1174                         else if (pred_code == iro_SymConst) {
1175                                 /* FIXME: in general, SymConst always require a load, so it
1176                                    might be better to place them into the first real block
1177                                    and let the spiller rematerialize them. */
1178                                 ident *id = get_sc_ident(pred);
1179                                 ir_node *symconst_node;
1180                                 symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1181                                         current_ir_graph, get_nodes_block(get_irn_n(get_nodes_block(node),i)),
1182                                         get_irn_mode(pred), id);
1183                                 set_irn_n(node, i, symconst_node);
1184                         }
1185                 }
1186                 return;
1187         }
1188         for (i = 0; i < get_irn_arity(node); i++) {
1189                 ir_node *pred = get_irn_n(node,i);
1190                 ir_opcode pred_code = get_irn_opcode(pred);
1191
1192                 if (pred_code == iro_Const) {
1193                         ir_node *block = get_nodes_block(node);
1194                         ir_node *nn    = gen_arm_Const(pred, block, cg);
1195                         set_irn_n(node, i, nn);
1196                 } else if (pred_code == iro_SymConst) {
1197                         ident *id = get_sc_ident(pred);
1198                         ir_node *symconst_node;
1199                         symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1200                                 current_ir_graph, get_nodes_block(node),
1201                                 get_irn_mode(pred), id);
1202                         set_irn_n(node, i, symconst_node);
1203                 }
1204         }
1205 }
1206
1207 /**
1208  * Do not transform Proj, but check for floating point value.
1209  */
1210 static ir_node *gen_Proj(ir_node *irn, arm_code_gen_t *cg) {
1211         if (mode_is_float(get_irn_mode(irn)))
1212                 cg->have_fp = 1;
1213         return NULL;
1214 }
1215
1216
1217 /**
1218  * the BAD transformer.
1219  */
1220 static ir_node *bad_transform(ir_node *irn, arm_code_gen_t *cg) {
1221         ir_fprintf(stderr, "Not implemented: %+F\n", irn);
1222         assert(0);
1223         return NULL;
1224 }
1225
1226 /**
1227  * The type of a transform function.
1228  */
1229 typedef ir_node *(transform_func)(ir_node *irn, arm_code_gen_t *cg);
1230
1231 /**
1232  * Set a node emitter. Make it a bit more type safe.
1233  */
1234 static INLINE void set_transformer(ir_op *op, transform_func arm_transform_func) {
1235         op->ops.generic = (op_func)arm_transform_func;
1236 }
1237
1238 /**
1239  * Enters all transform functions into the generic pointer
1240  */
1241 void arm_register_transformers(void) {
1242         ir_op *op_Max, *op_Min, *op_Mulh;
1243
1244         /* first clear the generic function pointer for all ops */
1245         clear_irp_opcodes_generic_func();
1246
1247 #define FIRM_OP(a)     set_transformer(op_##a, gen_##a)
1248 #define BAD(a)         set_transformer(op_##a, bad_transform)
1249 #define IGN(a)
1250
1251         FIRM_OP(Add);  // done
1252         FIRM_OP(Mul);  // done
1253         FIRM_OP(Quot); // done
1254         FIRM_OP(And);  // done
1255         FIRM_OP(Or);   // done
1256         FIRM_OP(Eor);  // done
1257
1258         FIRM_OP(Sub);  // done
1259         FIRM_OP(Shl);  // done
1260         FIRM_OP(Shr);  // done
1261         FIRM_OP(Shrs); // done
1262
1263         FIRM_OP(Minus); // done
1264         FIRM_OP(Not);   // done
1265         FIRM_OP(Abs);   // done
1266
1267         FIRM_OP(CopyB); // done
1268         BAD(Const);     /* should be handled by arm_move_const */
1269         FIRM_OP(Conv); // TODO: floating point conversions
1270
1271         FIRM_OP(Load);   // done
1272         FIRM_OP(Store);  // done
1273
1274         FIRM_OP(SymConst);
1275         FIRM_OP(Cond);    // integer done
1276
1277         /* TODO: implement these nodes */
1278
1279         IGN(Div);    // intrinsic lowering
1280         IGN(Mod);    // intrinsic lowering
1281         IGN(DivMod); // TODO: implement DivMod
1282
1283         IGN(Mux);
1284         IGN(Unknown);
1285         IGN(Cmp);     // done, implemented in cond
1286
1287         /* You probably don't need to handle the following nodes */
1288
1289         IGN(Call);
1290         FIRM_OP(Proj);
1291         IGN(Alloc);
1292
1293         IGN(Block);
1294         IGN(Start);
1295         IGN(End);
1296         IGN(NoMem);
1297         IGN(Phi);
1298         IGN(IJmp);
1299         IGN(Jmp);     // emitter done
1300         IGN(Break);
1301         IGN(Sync);
1302
1303         BAD(Raise);
1304         BAD(Sel);
1305         BAD(InstOf);
1306         BAD(Cast);
1307         BAD(Free);
1308         BAD(Tuple);
1309         BAD(Id);
1310         BAD(Bad);
1311         BAD(Confirm);
1312         BAD(Filter);
1313         BAD(CallBegin);
1314         BAD(EndReg);
1315         BAD(EndExcept);
1316
1317         FIRM_OP(be_FrameAddr);
1318
1319         op_Max = get_op_Max();
1320         if (op_Max)
1321                 BAD(Max);
1322         op_Min = get_op_Min();
1323         if (op_Min)
1324                 BAD(Min);
1325         op_Mulh = get_op_Mulh();
1326         if (op_Mulh)
1327                 BAD(Mulh);
1328
1329 #undef IGN
1330 #undef FIRM_OP
1331 #undef BAD
1332 }
1333
1334 /**
1335  * Transforms the given firm node (and maybe some other related nodes)
1336  * into one or more assembler nodes.
1337  *
1338  * @param node    the firm node
1339  * @param env     the debug module
1340  */
1341 void arm_transform_node(ir_node *node, void *env) {
1342         arm_code_gen_t *cg = (arm_code_gen_t *)env;
1343         ir_op *op          = get_irn_op(node);
1344         ir_node *asm_node  = NULL;
1345
1346         if (op == op_Block)
1347                 return;
1348
1349         DBG((cg->mod, LEVEL_1, "check %+F ... ", node));
1350
1351         if (op->ops.generic) {
1352                 transform_func *transform = (transform_func *)op->ops.generic;
1353
1354                 asm_node = (*transform)(node, cg);
1355         }
1356
1357         if (asm_node) {
1358                 exchange(node, asm_node);
1359                 DB((cg->mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1360         }
1361         else {
1362                 DB((cg->mod, LEVEL_1, "ignored\n"));
1363         }
1364 }