moved external headers into include dir
[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 /**
214  * Creates code for a Firm Const node.
215  */
216 static ir_node *gen_Const(ir_node *irn, arm_code_gen_t *cg) {
217         ir_graph *irg = current_ir_graph;
218         ir_node *block = get_nodes_block(irn);
219         ir_mode *mode = get_irn_mode(irn);
220         dbg_info *dbg = get_irn_dbg_info(irn);
221
222         if (mode_is_float(mode)) {
223                 if (USE_FPA(cg->isa))
224                         return new_rd_arm_fpaConst(dbg, irg, block, mode, get_Const_tarval(irn));
225                 else if (USE_VFP(cg->isa))
226                         assert(mode != mode_E && "IEEE Extended FP not supported");
227                 assert(0 && "NYI");
228         }
229         else if (mode_is_reference(mode))
230                 return irn;
231         return create_const_graph(cg->birg->abi, irn, block);
232 }
233
234 static ir_node *gen_mask(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) {
235         ir_node *block = get_nodes_block(irn);
236         unsigned mask_bits = (1 << result_bits) - 1;
237         ir_node *mask_node = create_const_graph_value(abi, irn, block, mask_bits);
238         dbg_info *dbg = get_irn_dbg_info(irn);
239         return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, get_irn_mode(irn), ARM_SHF_NONE, NULL);
240 }
241
242 static ir_node *gen_sign_extension(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) {
243         ir_node *block = get_nodes_block(irn);
244         int shift_width = 32 - result_bits;
245         ir_graph *irg = current_ir_graph;
246         ir_node *shift_const_node = create_const_graph_value(abi, irn, block, shift_width);
247         dbg_info *dbg = get_irn_dbg_info(irn);
248         ir_node *lshift_node = new_rd_arm_Shl(dbg, irg, block, op, shift_const_node, get_irn_mode(op));
249         ir_node *rshift_node = new_rd_arm_Shrs(dbg, irg, block, lshift_node, shift_const_node, get_irn_mode(irn));
250         return rshift_node;
251 }
252
253 /**
254  * Transforms a Conv node.
255  *
256  * @param env   The transformation environment
257  * @return the created arm Conv node
258  */
259 static ir_node *gen_Conv(ir_node *irn, arm_code_gen_t *cg) {
260         ir_graph *irg = current_ir_graph;
261         ir_node *block   = get_nodes_block(irn);
262         ir_node *op      = get_Conv_op(irn);
263         ir_mode *in_mode = get_irn_mode(op);
264         ir_mode *out_mode = get_irn_mode(irn);
265         dbg_info *dbg    = get_irn_dbg_info(irn);
266
267         if (in_mode == out_mode)
268                 return op;
269
270         if (mode_is_float(in_mode) || mode_is_float(out_mode)) {
271                 cg->have_fp = 1;
272
273                 if (USE_FPA(cg->isa)) {
274                         if (mode_is_float(in_mode)) {
275                                 if (mode_is_float(out_mode)) {
276                                         /* from float to float */
277                                         return new_rd_arm_fpaMov(dbg, irg, block, op, out_mode);
278                                 }
279                                 else {
280                                         /* from float to int */
281                                         return new_rd_arm_fpaFix(dbg, irg, block, op, out_mode);
282                                 }
283                         }
284                         else {
285                                 /* from int to float */
286                                 return new_rd_arm_fpaFlt(dbg, irg, block, op, out_mode);
287                         }
288                 }
289                 assert(0 && "NYI");
290         }
291         else { /* complete in gp registers */
292                 int in_bits  = get_mode_size_bits(in_mode);
293                 int out_bits = get_mode_size_bits(out_mode);
294                 int in_sign  = get_mode_sign(in_mode);
295                 int out_sign = get_mode_sign(out_mode);
296
297                 // 32 -> 32
298                         // NOPpen
299                 if (in_bits == out_bits && in_bits == 32)
300                         return op;
301
302                 // 16 -> 16
303                         // unsigned -> unsigned
304                                 // NOP
305                         // unsigned -> signed
306                                 // sign extension (31:16)=(15)
307                         // signed -> unsigned
308                                 // maskieren (31:16)=0
309                         // signed -> signed
310                                 // NOP
311                 if (in_bits == out_bits && out_bits < 32) {
312                         if (in_sign && !out_sign) {
313                                 return gen_mask(cg->birg->abi, irn, op, out_bits);
314                         } else {
315                                 return gen_sign_extension(cg->birg->abi, irn, op, out_bits);
316                         }
317                 }
318
319                 // 16 -> 32
320                         // unsigned -> unsigned
321                                 // NOP
322                         // unsigned -> signed
323                                 // NOP
324                         // signed -> unsigned
325                                 // sign extension (31:16)=(15)
326                         // signed -> signed
327                                 // sign extension (31:16)=(15)
328                 if (in_bits < out_bits) {
329                         if (in_sign) {
330                                 return gen_sign_extension(cg->birg->abi, irn, op, out_bits);
331                         } else {
332                                 return op;
333                         }
334                 }
335
336                 // 32 -> 16
337                         // unsigned -> unsigned
338                                 // maskieren (31:16)=0
339                         // unsigned -> signed
340                                 // maskieren (31:16)=0
341                         // signed -> unsigned
342                                 // maskieren (31:16)=0
343                         // signed -> signed
344                                 // sign extension (erledigt auch maskieren) (31:16)=(15)
345                 if (in_bits > out_bits) {
346                         if (in_sign && out_sign) {
347                                 return gen_sign_extension(cg->birg->abi, irn, op, out_bits);
348                         } else {
349                                 return gen_mask(cg->birg->abi, irn, op, out_bits);
350                         }
351                 }
352                 assert(0 && "recheck integer conversion logic!");
353                 return irn;
354         }
355         return NULL;
356 }
357
358 /**
359  * Return true if an operand is a shifter operand
360  */
361 static int is_shifter_operand(ir_node *n, arm_shift_modifier *pmod) {
362         arm_shift_modifier mod = ARM_SHF_NONE;
363
364         if (is_arm_Mov(n))
365                 mod = get_arm_shift_modifier(n);
366
367         *pmod = mod;
368         if (mod != ARM_SHF_NONE) {
369                 long v = get_tarval_long(get_arm_value(n));
370                 if (v < 32)
371                         return (int)v;
372         }
373         return 0;
374 }
375
376 /**
377  * Creates an arm Add.
378  *
379  * @param env   The transformation environment
380  * @return the created arm Add node
381  */
382 static ir_node *gen_Add(ir_node *irn, arm_code_gen_t *cg) {
383         ir_node *block = get_nodes_block(irn);
384         ir_node *op1 = get_Add_left(irn);
385         ir_node *op2 = get_Add_right(irn);
386         ir_mode *mode = get_irn_mode(irn);
387         ir_graph *irg = current_ir_graph;
388         ir_node *op3;
389         int v;
390         arm_shift_modifier mod;
391         dbg_info *dbg = get_irn_dbg_info(irn);
392
393         if (mode_is_float(mode)) {
394                 cg->have_fp = 1;
395                 if (USE_FPA(cg->isa))
396                         return new_rd_arm_fpaAdd(dbg, irg, block, op1, op2, mode);
397                 else if (USE_VFP(cg->isa)) {
398                         assert(mode != mode_E && "IEEE Extended FP not supported");
399                 }
400                 assert(0 && "NYI");
401         }
402         if (mode_is_numP(mode)) {
403                 if (is_arm_Mov_i(op1))
404                         return new_rd_arm_Add_i(dbg, irg, block, op2, mode, get_arm_value(op1));
405                 if (is_arm_Mov_i(op2))
406                         return new_rd_arm_Add_i(dbg, irg, block, op1, mode, get_arm_value(op2));
407
408                 /* check for MLA */
409                 if (is_arm_Mul(op1) && get_irn_n_edges(op1) == 1) {
410                         op3 = op2;
411                         op2 = get_irn_n(op1, 1);
412                         op1 = get_irn_n(op1, 0);
413
414                         return new_rd_arm_Mla(dbg, irg, block, op1, op2, op3, mode);
415                 }
416                 if (is_arm_Mul(op2) && get_irn_n_edges(op2) == 1) {
417                         op3 = op1;
418                         op1 = get_irn_n(op2, 0);
419                         op2 = get_irn_n(op2, 1);
420
421                         return new_rd_arm_Mla(dbg, irg, block, op1, op2, op3, mode);
422                 }
423
424                 /* is the first a shifter */
425                 v = is_shifter_operand(op1, &mod);
426                 if (v) {
427                         op1 = get_irn_n(op1, 0);
428                         return new_rd_arm_Add(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu));
429                 }
430                 /* is the second a shifter */
431                 v = is_shifter_operand(op2, &mod);
432                 if (v) {
433                         op2 = get_irn_n(op2, 0);
434                         return new_rd_arm_Add(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu));
435                 }
436
437                 /* normal ADD */
438                 return new_rd_arm_Add(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL);
439         }
440
441         assert(0 && "unknown mode for add");
442         return NULL;
443 }
444
445 /**
446  * Creates an arm Mul.
447  *
448  * @param env   The transformation environment
449  * @return the created arm Mul node
450  */
451 static ir_node *gen_Mul(ir_node *irn, arm_code_gen_t *cg) {
452         ir_node *block = get_nodes_block(irn);
453         ir_node *op1 = get_Mul_left(irn);
454         ir_node *op2 = get_Mul_right(irn);
455         ir_mode *mode = get_irn_mode(irn);
456         ir_graph *irg = current_ir_graph;
457         dbg_info *dbg = get_irn_dbg_info(irn);
458
459         if (mode_is_float(mode)) {
460                 cg->have_fp = 1;
461                 if (USE_FPA(cg->isa))
462                         return new_rd_arm_fpaMul(dbg, irg, block, op1, op2, mode);
463                 else if (USE_VFP(cg->isa)) {
464                         assert(mode != mode_E && "IEEE Extended FP not supported");
465                 }
466                 assert(0 && "NYI");
467         }
468         return new_rd_arm_Mul(dbg, irg, block, op1, op2, mode);
469 }
470
471 /**
472  * Creates an arm floating point Div.
473  *
474  * @param env   The transformation environment
475  * @return the created arm fDiv node
476  */
477 static ir_node *gen_Quot(ir_node *irn, arm_code_gen_t *cg) {
478         ir_node *block = get_nodes_block(irn);
479         ir_node *op1 = get_Quot_left(irn);
480         ir_node *op2 = get_Quot_right(irn);
481         ir_mode *mode = get_irn_mode(irn);
482         dbg_info *dbg = get_irn_dbg_info(irn);
483
484         assert(mode != mode_E && "IEEE Extended FP not supported");
485
486         cg->have_fp = 1;
487         if (USE_FPA(cg->isa))
488                 return new_rd_arm_fpaDiv(dbg, current_ir_graph, block, op1, op2, mode);
489         else if (USE_VFP(cg->isa)) {
490                 assert(mode != mode_E && "IEEE Extended FP not supported");
491         }
492         assert(0 && "NYI");
493
494         return NULL;
495 }
496
497 #define GEN_INT_OP(op) \
498 static ir_node *gen_ ## op(ir_node *irn, arm_code_gen_t *cg) { \
499         ir_graph *irg = current_ir_graph; \
500         ir_node *block = get_nodes_block(irn); \
501         ir_node *op1 = get_ ## op ## _left(irn); \
502         ir_node *op2 = get_ ## op ## _right(irn); \
503         int v; \
504         arm_shift_modifier mod; \
505         ir_mode *mode = get_irn_mode(irn); \
506         dbg_info *dbg = get_irn_dbg_info(irn); \
507  \
508         if (is_arm_Mov_i(op1)) \
509                 return new_rd_arm_ ## op ## _i(dbg, irg, block, op2, mode, get_arm_value(op1)); \
510         if (is_arm_Mov_i(op2)) \
511                 return new_rd_arm_ ## op ## _i(dbg, irg, block, op1, mode, get_arm_value(op2)); \
512         /* is the first a shifter */ \
513         v = is_shifter_operand(op1, &mod); \
514         if (v) { \
515                 op1 = get_irn_n(op1, 0); \
516                 return new_rd_arm_ ## op(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu)); \
517         } \
518         /* is the second a shifter */ \
519         v = is_shifter_operand(op2, &mod); \
520         if (v) { \
521                 op2 = get_irn_n(op2, 0); \
522                 return new_rd_arm_ ## op(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu)); \
523         } \
524         /* Normal op */ \
525         return new_rd_arm_ ## op(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL); \
526 }
527
528
529 /**
530  * Creates an arm And.
531  *
532  * @param env   The transformation environment
533  * @return the created arm And node
534  */
535 static ir_node *gen_And(ir_node *irn, arm_code_gen_t *cg);
536 GEN_INT_OP(And)
537
538 /**
539  * Creates an arm Orr.
540  *
541  * @param env   The transformation environment
542  * @return the created arm Or node
543  */
544 static ir_node *gen_Or(ir_node *irn, arm_code_gen_t *cg);
545 GEN_INT_OP(Or)
546
547 /**
548  * Creates an arm Eor.
549  *
550  * @param env   The transformation environment
551  * @return the created arm Eor node
552  */
553 static ir_node *gen_Eor(ir_node *irn, arm_code_gen_t *cg);
554 GEN_INT_OP(Eor)
555
556 /**
557  * Creates an arm Sub.
558  *
559  * @param env   The transformation environment
560  * @return the created arm Sub node
561  */
562 static ir_node *gen_Sub(ir_node *irn, arm_code_gen_t *cg) {
563         ir_node *block = get_nodes_block(irn);
564         ir_node *op1 = get_Sub_left(irn);
565         ir_node *op2 = get_Sub_right(irn);
566         int v;
567         arm_shift_modifier mod;
568         ir_mode *mode = get_irn_mode(irn);
569         ir_graph *irg = current_ir_graph;
570         dbg_info *dbg = get_irn_dbg_info(irn);
571
572         if (mode_is_float(mode)) {
573                 cg->have_fp = 1;
574                 if (USE_FPA(cg->isa))
575                         return new_rd_arm_fpaSub(dbg, irg, block, op1, op2, mode);
576                 else if (USE_VFP(cg->isa)) {
577                         assert(mode != mode_E && "IEEE Extended FP not supported");
578                 }
579                 assert(0 && "NYI");
580         }
581         if (mode_is_numP(mode)) {
582                 if (is_arm_Mov_i(op1))
583                         return new_rd_arm_Rsb_i(dbg, irg, block, op2, mode, get_arm_value(op1));
584                 if (is_arm_Mov_i(op2))
585                         return new_rd_arm_Sub_i(dbg, irg, block, op1, mode, get_arm_value(op2));
586
587                 /* is the first a shifter */
588                 v = is_shifter_operand(op1, &mod);
589                 if (v) {
590                         op1 = get_irn_n(op1, 0);
591                         return new_rd_arm_Rsb(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu));
592                 }
593                 /* is the second a shifter */
594                 v = is_shifter_operand(op2, &mod);
595                 if (v) {
596                         op2 = get_irn_n(op2, 0);
597                         return new_rd_arm_Sub(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu));
598                 }
599                 /* normal sub */
600                 return new_rd_arm_Sub(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL);
601         }
602         assert(0 && "unknown mode for sub");
603         return NULL;
604 }
605
606 /**
607  * Creates an arm Shl.
608  *
609  * @param env   The transformation environment
610  * @return the created arm Shl node
611  */
612 static ir_node *gen_Shl(ir_node *irn, arm_code_gen_t *cg) {
613         ir_node *result;
614         ir_node *block = get_nodes_block(irn);
615         ir_node *op1 = get_Shl_left(irn);
616         ir_node *op2 = get_Shl_right(irn);
617         ir_mode *mode = get_irn_mode(irn);
618         ir_graph *irg = current_ir_graph;
619         dbg_info *dbg = get_irn_dbg_info(irn);
620
621         if (is_arm_Mov_i(op2)) {
622                 result = new_rd_arm_Mov(dbg, irg, block, op1, mode, ARM_SHF_LSL, get_arm_value(op2));
623         } else {
624                 result = new_rd_arm_Shl(dbg, irg, block, op1, op2, mode);
625         }
626         return result;
627 }
628
629 /**
630  * Creates an arm Shr.
631  *
632  * @param env   The transformation environment
633  * @return the created arm Shr node
634  */
635 static ir_node *gen_Shr(ir_node *irn, arm_code_gen_t *cg) {
636         ir_node *result;
637         ir_node *block = get_nodes_block(irn);
638         ir_node *op1 = get_Shr_left(irn);
639         ir_node *op2 = get_Shr_right(irn);
640         ir_mode *mode = get_irn_mode(irn);
641         ir_graph *irg = current_ir_graph;
642         dbg_info *dbg = get_irn_dbg_info(irn);
643
644         if (is_arm_Mov_i(op2)) {
645                 result = new_rd_arm_Mov(dbg, irg, block, op1, mode, ARM_SHF_LSR, get_arm_value(op2));
646         } else {
647                 result = new_rd_arm_Shr(dbg, irg, block, op1, op2, mode);
648         }
649         return result;
650 }
651
652 /**
653  * Creates an arm Shrs.
654  *
655  * @param env   The transformation environment
656  * @return the created arm Shrs node
657  */
658 static ir_node *gen_Shrs(ir_node *irn, arm_code_gen_t *cg) {
659         ir_node *result;
660         ir_node *block = get_nodes_block(irn);
661         ir_node *op1 = get_Shrs_left(irn);
662         ir_node *op2 = get_Shrs_right(irn);
663         ir_mode *mode = get_irn_mode(irn);
664         dbg_info *dbg = get_irn_dbg_info(irn);
665
666         if (is_arm_Mov_i(op2)) {
667                 result = new_rd_arm_Mov(dbg, current_ir_graph, block, op1, mode, ARM_SHF_ASR, get_arm_value(op2));
668         } else {
669                 result = new_rd_arm_Shrs(dbg, current_ir_graph, block, op1, op2, mode);
670         }
671         return result;
672 }
673
674 /**
675  * Transforms a Not node.
676  *
677  * @param env   The transformation environment
678  * @return the created arm Not node
679  */
680 static ir_node *gen_Not(ir_node *irn, arm_code_gen_t *cg) {
681         ir_node *block = get_nodes_block(irn);
682         ir_node *op = get_Not_op(irn);
683         int v;
684         arm_shift_modifier mod = ARM_SHF_NONE;
685         tarval  *tv = NULL;
686         dbg_info *dbg = get_irn_dbg_info(irn);
687
688         v = is_shifter_operand(op, &mod);
689         if (v) {
690                 op = get_irn_n(op, 0);
691                 tv = new_tarval_from_long(v, mode_Iu);
692         }
693         return new_rd_arm_Mvn(dbg, current_ir_graph, block, op, get_irn_mode(irn), mod, tv);
694 }
695
696 /**
697  * Transforms an Abs node.
698  *
699  * @param env   The transformation environment
700  * @return the created arm Abs node
701  */
702 static ir_node *gen_Abs(ir_node *irn, arm_code_gen_t *cg) {
703         ir_node *block = get_nodes_block(irn);
704         ir_node *op = get_Abs_op(irn);
705         ir_mode *mode = get_irn_mode(irn);
706         dbg_info *dbg = get_irn_dbg_info(irn);
707
708         if (mode_is_float(mode)) {
709                 cg->have_fp = 1;
710                 if (USE_FPA(cg->isa))
711                         return new_rd_arm_fpaAbs(dbg, current_ir_graph, block, op, mode);
712                 else if (USE_VFP(cg->isa)) {
713                         assert(mode != mode_E && "IEEE Extended FP not supported");
714                 }
715                 assert(0 && "NYI");
716         }
717         return new_rd_arm_Abs(dbg, current_ir_graph, block, op, mode);
718 }
719
720 /**
721  * Transforms a Minus node.
722  *
723  * @param env   The transformation environment
724  * @return the created arm Minus node
725  */
726 static ir_node *gen_Minus(ir_node *irn, arm_code_gen_t *cg) {
727         ir_node *block = get_nodes_block(irn);
728         ir_node *op = get_Minus_op(irn);
729         ir_mode *mode = get_irn_mode(irn);
730         ir_graph *irg = current_ir_graph;
731         dbg_info *dbg = get_irn_dbg_info(irn);
732
733         if (mode_is_float(mode)) {
734                 cg->have_fp = 1;
735                 if (USE_FPA(cg->isa))
736                         return new_rd_arm_fpaMnv(dbg, irg, block, op, mode);
737                 else if (USE_VFP(cg->isa)) {
738                         assert(mode != mode_E && "IEEE Extended FP not supported");
739                 }
740                 assert(0 && "NYI");
741         }
742         return new_rd_arm_Rsb_i(dbg, irg, block, op, mode, get_mode_null(mode));
743 }
744
745 /**
746  * Transforms a Load.
747  *
748  * @param mod     the debug module
749  * @param block   the block the new node should belong to
750  * @param node    the ir Load node
751  * @param mode    node mode
752  * @return the created arm Load node
753  */
754 static ir_node *gen_Load(ir_node *irn, arm_code_gen_t *cg) {
755         ir_node *block = get_nodes_block(irn);
756         ir_mode *mode = get_Load_mode(irn);
757         ir_graph *irg = current_ir_graph;
758         dbg_info *dbg = get_irn_dbg_info(irn);
759
760         if (mode_is_float(mode)) {
761                 cg->have_fp = 1;
762                 if (USE_FPA(cg->isa))
763                         return new_rd_arm_fpaLdf(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn),
764                                 get_Load_mode(irn));
765                 else if (USE_VFP(cg->isa)) {
766                         assert(mode != mode_E && "IEEE Extended FP not supported");
767                 }
768                 assert(0 && "NYI");
769         }
770         if (mode == mode_Bu) {
771                 return new_rd_arm_Loadb(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
772         }
773         if (mode == mode_Bs) {
774                 return new_rd_arm_Loadbs(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
775         }
776         if (mode == mode_Hu) {
777                 return new_rd_arm_Loadh(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
778         }
779         if (mode == mode_Hs) {
780                 return new_rd_arm_Loadhs(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
781         }
782         if (mode_is_reference(mode)) {
783                 return new_rd_arm_Load(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
784         }
785         return new_rd_arm_Load(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
786 }
787
788 /**
789  * Transforms a Store.
790  *
791  * @param mod     the debug module
792  * @param block   the block the new node should belong to
793  * @param node    the ir Store node
794  * @param mode    node mode
795  * @return the created arm Store node
796  */
797 static ir_node *gen_Store(ir_node *irn, arm_code_gen_t *cg) {
798         ir_node *block = get_nodes_block(irn);
799         ir_mode *mode = get_irn_mode(get_Store_value(irn));
800         ir_graph *irg = current_ir_graph;
801         dbg_info *dbg = get_irn_dbg_info(irn);
802
803         assert(mode != mode_E && "IEEE Extended FP not supported");
804         if (mode_is_float(mode)) {
805                 cg->have_fp = 1;
806                 if (USE_FPA(cg->isa))
807                         return new_rd_arm_fpaStf(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn),
808                                 get_Store_mem(irn), get_irn_mode(get_Store_value(irn)));
809                 else if (USE_VFP(cg->isa)) {
810                         assert(mode != mode_E && "IEEE Extended FP not supported");
811                 }
812                 assert(0 && "NYI");
813         }
814         if (mode == mode_Bu) {
815                 return new_rd_arm_Storeb(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
816         }
817         if (mode == mode_Bs) {
818                 return new_rd_arm_Storebs(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
819         }
820         if (mode == mode_Hu) {
821                 return new_rd_arm_Storeh(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
822         }
823         if (mode == mode_Hs) {
824                 return new_rd_arm_Storehs(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
825         }
826         return new_rd_arm_Store(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
827 }
828
829
830 static ir_node *gen_Cond(ir_node *irn, arm_code_gen_t *cg) {
831         ir_node *result   = NULL;
832         ir_node *selector = get_Cond_selector(irn);
833         ir_node *block    = get_nodes_block(irn);
834         ir_graph *irg     = current_ir_graph;
835         dbg_info *dbg     = get_irn_dbg_info(irn);
836
837         if ( get_irn_mode(selector) == mode_b ) {
838                 //CondJmp
839                 ir_node *proj_node = get_Cond_selector(irn);
840                 ir_node *cmp_node = get_Proj_pred(proj_node);
841                 ir_node *op1 = get_Cmp_left(cmp_node);
842                 ir_node *op2 = get_Cmp_right(cmp_node);
843                 result = new_rd_arm_CondJmp(dbg, irg, block, op1, op2, mode_T);
844                 set_arm_proj_num(result, get_Proj_proj(proj_node));
845         } else {
846                 //SwitchJmp
847                 ir_node *op = get_irn_n(irn, 0);
848                 ir_node *const_graph;
849                 ir_node *sub;
850                 ir_node *const_node;
851
852                 ir_node *proj;
853                 const ir_edge_t *edge;
854                 int min = INT_MAX;
855                 int max = INT_MIN;
856                 int translation;
857                 int norm_max;
858                 int norm_min;
859                 int pn;
860                 int n_projs;
861                 ir_node **projs;
862
863                 foreach_out_edge(irn, edge) {
864                         proj = get_edge_src_irn(edge);
865                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
866
867                         pn = get_Proj_proj(proj);
868
869                         min = pn<min ? pn : min;
870                         max = pn>max ? pn : max;
871                 }
872                 translation = min;
873                 norm_max = max - translation;
874                 norm_min = min - translation;
875
876                 n_projs = norm_max + 1;
877                 projs = xcalloc(n_projs , sizeof(ir_node*));
878
879
880                 foreach_out_edge(irn, edge) {
881                         proj = get_edge_src_irn(edge);
882                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
883
884                         pn = get_Proj_proj(proj) - translation;
885                         set_Proj_proj(proj, pn);
886                 }
887
888
889                 const_node = new_rd_Const(dbg, irg, block, mode_Iu, new_tarval_from_long(translation, mode_Iu));
890                 const_graph = gen_Const(const_node, cg);
891                 sub = new_rd_arm_Sub(dbg, irg, block, op, const_graph, get_irn_mode(op), ARM_SHF_NONE, NULL);
892                 result = new_rd_arm_SwitchJmp(dbg, irg, block, sub, mode_T);
893                 set_arm_n_projs(result, n_projs);
894                 set_arm_default_proj_num(result, get_Cond_defaultProj(irn)-translation);
895         }
896         return result;
897 }
898
899 /**
900  * Returns the name of a SymConst.
901  * @param symc  the SymConst
902  * @return name of the SymConst
903  */
904 ident *get_sc_ident(ir_node *symc) {
905         ir_entity *ent;
906
907         switch (get_SymConst_kind(symc)) {
908                 case symconst_addr_name:
909                         return get_SymConst_name(symc);
910
911                 case symconst_addr_ent:
912                         ent = get_SymConst_entity(symc);
913                         mark_entity_visited(ent);
914                         return get_entity_ld_ident(ent);
915
916                 default:
917                         assert(0 && "Unsupported SymConst");
918         }
919
920         return NULL;
921 }
922
923 static ir_node *gen_SymConst(ir_node *irn, arm_code_gen_t *cg) {
924         ir_node *block = get_nodes_block(irn);
925         ir_mode *mode = get_irn_mode(irn);
926         dbg_info *dbg = get_irn_dbg_info(irn);
927         return new_rd_arm_SymConst(dbg, current_ir_graph, block, mode, get_sc_ident(irn));
928 }
929
930
931
932 /**
933  * Transforms a CopyB node.
934  *
935  * @param env   The transformation environment
936  * @return The transformed node.
937  */
938 static ir_node *gen_CopyB(ir_node *irn, arm_code_gen_t *cg) {
939         ir_node  *res   = NULL;
940         dbg_info *dbg   = get_irn_dbg_info(irn);
941         ir_mode  *mode  = get_irn_mode(irn);
942         ir_node  *src   = get_CopyB_src(irn);
943         ir_node  *dst   = get_CopyB_dst(irn);
944         ir_node  *mem   = get_CopyB_mem(irn);
945         ir_node  *block = get_nodes_block(irn);
946         int       size  = get_type_size_bytes(get_CopyB_type(irn));
947         ir_graph *irg   = current_ir_graph;
948         ir_node *src_copy;
949         ir_node *dst_copy;
950
951         src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, src);
952         dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, dst);
953
954         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);
955         set_arm_value(res, new_tarval_from_long(size, mode_Iu));
956
957         return res;
958 }
959
960
961
962
963
964 /********************************************
965  *  _                          _
966  * | |                        | |
967  * | |__   ___ _ __   ___   __| | ___  ___
968  * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
969  * | |_) |  __/ | | | (_) | (_| |  __/\__ \
970  * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
971  *
972  ********************************************/
973
974 /**
975  * Return an expanding stack offset.
976  * Note that function is called in the transform phase
977  * where the stack offsets are still relative regarding
978  * the first (frame allocating) IncSP.
979  * However this is exactly what we want because frame
980  * access must be done relative the the fist IncSP ...
981  */
982 static int get_sp_expand_offset(ir_node *inc_sp) {
983         int offset = be_get_IncSP_offset(inc_sp);
984
985         if (offset == BE_STACK_FRAME_SIZE_EXPAND)
986                 return 0;
987
988         return offset;
989 }
990
991 #if 0
992 static ir_node *gen_StackParam(ir_node *irn, arm_code_gen_t *cg) {
993         ir_node   *new_op = NULL;
994         ir_node   *block  = get_nodes_block(irn);
995         ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
996         ir_node   *mem    = new_rd_NoMem(env->irg);
997         ir_node   *ptr    = get_irn_n(irn, 0);
998         ir_entity *ent    = be_get_frame_entity(irn);
999         ir_mode   *mode   = env->mode;
1000
1001 //      /* If the StackParam has only one user ->     */
1002 //      /* put it in the Block where the user resides */
1003 //      if (get_irn_n_edges(node) == 1) {
1004 //              env->block = get_nodes_block(get_edge_src_irn(get_irn_out_edge_first(node)));
1005 //      }
1006
1007         if (mode_is_float(mode)) {
1008                 if (USE_SSE2(env->cg))
1009                         new_op = new_rd_ia32_fLoad(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1010                 else {
1011                         env->cg->used_x87 = 1;
1012                         new_op = new_rd_ia32_vfld(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1013                 }
1014         }
1015         else {
1016                 new_op = new_rd_ia32_Load(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1017         }
1018
1019         set_ia32_frame_ent(new_op, ent);
1020         set_ia32_use_frame(new_op);
1021
1022         set_ia32_am_support(new_op, ia32_am_Source);
1023         set_ia32_op_type(new_op, ia32_AddrModeS);
1024         set_ia32_am_flavour(new_op, ia32_B);
1025         set_ia32_ls_mode(new_op, mode);
1026
1027         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1028
1029         return new_rd_Proj(env->dbg, env->irg, block, new_op, mode, 0);
1030 }
1031 #endif
1032
1033 /**
1034  * Transforms a FrameAddr into an ia32 Add.
1035  */
1036 static ir_node *gen_be_FrameAddr(ir_node *irn, arm_code_gen_t *cg) {
1037         ir_node *block  = get_nodes_block(irn);
1038         ir_entity *ent  = be_get_frame_entity(irn);
1039         int     offset  = get_entity_offset(ent);
1040         ir_node *op     = get_irn_n(irn, 0);
1041         ir_node *cnst;
1042         ir_mode *mode   = get_irn_mode(irn);
1043         dbg_info *dbg   = get_irn_dbg_info(irn);
1044
1045         if (be_is_IncSP(op)) {
1046                 /* BEWARE: we get an offset which is absolute from an offset that
1047                    is relative. Both must be merged */
1048                 offset += get_sp_expand_offset(op);
1049         }
1050         cnst = create_const_graph_value(cg->birg->abi, irn, block, (unsigned)offset);
1051         if (is_arm_Mov_i(cnst))
1052                 return new_rd_arm_Add_i(dbg, current_ir_graph, block, op, mode, get_arm_value(cnst));
1053         return new_rd_arm_Add(dbg, current_ir_graph, block, op, cnst, mode, ARM_SHF_NONE, NULL);
1054 }
1055
1056 #if 0
1057 /**
1058  * Transforms a FrameLoad into an ia32 Load.
1059  */
1060 static ir_node *gen_FrameLoad(ir_node *irn, arm_code_gen_t *cg) {
1061         ir_node   *new_op = NULL;
1062         ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
1063         ir_node   *mem    = get_irn_n(irn, 0);
1064         ir_node   *ptr    = get_irn_n(irn, 1);
1065         ir_entity *ent    = be_get_frame_entity(irn);
1066         ir_mode   *mode   = get_type_mode(get_entity_type(ent));
1067
1068         if (mode_is_float(mode)) {
1069                 if (USE_SSE2(env->cg))
1070                         new_op = new_rd_ia32_fLoad(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
1071                 else {
1072                         env->cg->used_x87 = 1;
1073                         new_op = new_rd_ia32_vfld(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
1074                 }
1075         }
1076         else {
1077                 new_op = new_rd_ia32_Load(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
1078         }
1079
1080         set_ia32_frame_ent(new_op, ent);
1081         set_ia32_use_frame(new_op);
1082
1083         set_ia32_am_support(new_op, ia32_am_Source);
1084         set_ia32_op_type(new_op, ia32_AddrModeS);
1085         set_ia32_am_flavour(new_op, ia32_B);
1086         set_ia32_ls_mode(new_op, mode);
1087
1088         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1089
1090         return new_op;
1091 }
1092 #endif
1093
1094 #if 0
1095 /**
1096  * Transforms a FrameStore into an ia32 Store.
1097  */
1098 static ir_node *gen_FrameStore(ir_node *irn, arm_code_gen_t *cg) {
1099         ir_node   *new_op = NULL;
1100         ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
1101         ir_node   *mem    = get_irn_n(irn, 0);
1102         ir_node   *ptr    = get_irn_n(irn, 1);
1103         ir_node   *val    = get_irn_n(irn, 2);
1104         ir_entity *ent    = be_get_frame_entity(irn);
1105         ir_mode   *mode   = get_irn_mode(val);
1106
1107         if (mode_is_float(mode)) {
1108                 if (USE_SSE2(env->cg))
1109                         new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1110                 else {
1111                         env->cg->used_x87 = 1;
1112                         new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1113                 }
1114         }
1115         else if (get_mode_size_bits(mode) == 8) {
1116                 new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1117         }
1118         else {
1119                 new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1120         }
1121
1122         set_ia32_frame_ent(new_op, ent);
1123         set_ia32_use_frame(new_op);
1124
1125         set_ia32_am_support(new_op, ia32_am_Dest);
1126         set_ia32_op_type(new_op, ia32_AddrModeD);
1127         set_ia32_am_flavour(new_op, ia32_B);
1128         set_ia32_ls_mode(new_op, mode);
1129
1130         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1131
1132         return new_op;
1133 }
1134 #endif
1135
1136
1137 // static ir_node *gen_be_Copy(ir_node *irn, arm_code_gen_t *cg) {
1138 //      return new_rd_arm_Copy(env->dbg, env->irg, env->block, op, env->mode);
1139 // }
1140
1141 /*********************************************************
1142  *                  _             _      _
1143  *                 (_)           | |    (_)
1144  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
1145  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
1146  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
1147  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
1148  *
1149  *********************************************************/
1150
1151 /**
1152  * move constants out of the start block
1153  */
1154 void arm_move_consts(ir_node *node, void *env) {
1155         arm_code_gen_t *cg = env;
1156         int i;
1157
1158         if (is_Block(node))
1159                 return;
1160
1161         if (is_Phi(node)) {
1162                 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
1163                         ir_node *pred = get_irn_n(node,i);
1164                         ir_opcode pred_code = get_irn_opcode(pred);
1165                         if (pred_code == iro_Const) {
1166                                 ir_node *const_graph;
1167                                 const_graph = create_const_graph(cg->birg->abi, pred, get_nodes_block(get_irn_n(get_nodes_block(node),i)));
1168                                 set_irn_n(node, i, const_graph);
1169                         }
1170                         else if (pred_code == iro_SymConst) {
1171                                 /* FIXME: in general, SymConst always require a load, so it
1172                                    might be better to place them into the first real block
1173                                    and let the spiller rematerialize them. */
1174                                 ident *id = get_sc_ident(pred);
1175                                 ir_node *symconst_node;
1176                                 symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1177                                         current_ir_graph, get_nodes_block(get_irn_n(get_nodes_block(node),i)),
1178                                         get_irn_mode(pred), id);
1179                                 set_irn_n(node, i, symconst_node);
1180                         }
1181                 }
1182                 return;
1183         }
1184         for (i = 0; i < get_irn_arity(node); i++) {
1185                 ir_node *pred = get_irn_n(node,i);
1186                 ir_opcode pred_code = get_irn_opcode(pred);
1187                 if (pred_code == iro_Const) {
1188                         ir_node *const_graph;
1189                         const_graph = create_const_graph(cg->birg->abi, pred, get_nodes_block(node));
1190                         set_irn_n(node, i, const_graph);
1191                 } else if (pred_code == iro_SymConst) {
1192                         ident *id = get_sc_ident(pred);
1193                         ir_node *symconst_node;
1194                         symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1195                                 current_ir_graph, get_nodes_block(node),
1196                                 get_irn_mode(pred), id);
1197                         set_irn_n(node, i, symconst_node);
1198                 }
1199         }
1200 }
1201
1202
1203 /************************************************************************/
1204 /* move symbolic constants out of startblock                            */
1205 /************************************************************************/
1206 void arm_move_symconsts(ir_node *node, void *env) {
1207         int i;
1208
1209         if (is_Block(node))
1210                 return;
1211
1212         for (i = 0; i < get_irn_arity(node); i++) {
1213                 ir_node *pred       = get_irn_n(node,i);
1214                 ir_opcode pred_code = get_irn_opcode(pred);
1215
1216                 if (pred_code == iro_SymConst) {
1217                         ident   *id = get_sc_ident(pred);
1218                         ir_node *symconst_node;
1219
1220                         symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1221                                 current_ir_graph, get_nodes_block(node), get_irn_mode(pred), id);
1222                         set_irn_n(node, i, symconst_node);
1223                 }
1224         }
1225 }
1226
1227 /**
1228  * the BAD transformer.
1229  */
1230 static ir_node *bad_transform(ir_node *irn, arm_code_gen_t *cg) {
1231         ir_fprintf(stderr, "Not implemented: %+F\n", irn);
1232         assert(0);
1233         return NULL;
1234 }
1235
1236 /**
1237  * Enters all transform functions into the generic pointer
1238  */
1239 void arm_register_transformers(void) {
1240         ir_op *op_Max, *op_Min, *op_Mulh;
1241
1242         /* first clear the generic function pointer for all ops */
1243         clear_irp_opcodes_generic_func();
1244
1245 #define FIRM_OP(a)     op_##a->ops.generic = (op_func)gen_##a
1246 #define BAD(a)         op_##a->ops.generic = (op_func)bad_transform
1247 #define IGN(a)
1248
1249         FIRM_OP(Add);  // done
1250         FIRM_OP(Mul);  // done
1251         FIRM_OP(Quot); // done
1252         FIRM_OP(And);  // done
1253         FIRM_OP(Or);   // done
1254         FIRM_OP(Eor);  // done
1255
1256         FIRM_OP(Sub);  // done
1257         FIRM_OP(Shl);  // done
1258         FIRM_OP(Shr);  // done
1259         FIRM_OP(Shrs); // done
1260
1261         FIRM_OP(Minus); // done
1262         FIRM_OP(Not);   // done
1263         FIRM_OP(Abs);   // done
1264
1265         FIRM_OP(CopyB); // done
1266         FIRM_OP(Const); // TODO: floating point consts
1267         FIRM_OP(Conv); // TODO: floating point conversions
1268
1269         FIRM_OP(Load);   // done
1270         FIRM_OP(Store);  // done
1271
1272         FIRM_OP(SymConst);
1273         FIRM_OP(Cond);    // integer done
1274
1275         /* TODO: implement these nodes */
1276
1277         IGN(Div);    // intrinsic lowering
1278         IGN(Mod);    // intrinsic lowering
1279         IGN(DivMod); // TODO: implement DivMod
1280
1281         IGN(Mux);
1282         IGN(Unknown);
1283         IGN(Cmp);     // done, implemented in cond
1284
1285         /* You probably don't need to handle the following nodes */
1286
1287         IGN(Call);
1288         IGN(Proj);
1289         IGN(Alloc);
1290
1291         IGN(Block);
1292         IGN(Start);
1293         IGN(End);
1294         IGN(NoMem);
1295         IGN(Phi);
1296         IGN(IJmp);
1297         IGN(Jmp);     // emitter done
1298         IGN(Break);
1299         IGN(Sync);
1300
1301         BAD(Raise);
1302         BAD(Sel);
1303         BAD(InstOf);
1304         BAD(Cast);
1305         BAD(Free);
1306         BAD(Tuple);
1307         BAD(Id);
1308         BAD(Bad);
1309         BAD(Confirm);
1310         BAD(Filter);
1311         BAD(CallBegin);
1312         BAD(EndReg);
1313         BAD(EndExcept);
1314
1315         FIRM_OP(be_FrameAddr);
1316
1317         op_Max = get_op_Max();
1318         if (op_Max)
1319                 BAD(Max);
1320         op_Min = get_op_Min();
1321         if (op_Min)
1322                 BAD(Min);
1323         op_Mulh = get_op_Mulh();
1324         if (op_Mulh)
1325                 BAD(Mulh);
1326
1327 #undef IGN
1328 #undef FIRM_OP
1329 #undef BAD
1330 }
1331
1332 typedef ir_node *(transform_func)(ir_node *irn, arm_code_gen_t *cg);
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 }