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