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