used entities are now marked
[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         ir_entity *ent;
899         if (get_irn_opcode(symc) != iro_SymConst)
900                 return "NONE";
901
902         switch (get_SymConst_kind(symc)) {
903                 case symconst_addr_name:
904                         return get_id_str(get_SymConst_name(symc));
905
906                 case symconst_addr_ent:
907                         ent = get_SymConst_entity(symc);
908                         mark_entity_visited(ent);
909                         return get_entity_ld_name(ent);
910
911                 default:
912                         assert(0 && "Unsupported SymConst");
913         }
914
915         return NULL;
916 }
917
918 static ir_node *gen_SymConst(ir_node *irn, arm_code_gen_t *cg) {
919         ir_node *block = get_nodes_block(irn);
920         ir_mode *mode = get_irn_mode(irn);
921         dbg_info *dbg = get_irn_dbg_info(irn);
922         return new_rd_arm_SymConst(dbg, current_ir_graph, block, mode, get_sc_name(irn));
923 }
924
925
926
927 /**
928  * Transforms a CopyB node.
929  *
930  * @param env   The transformation environment
931  * @return The transformed node.
932  */
933 static ir_node *gen_CopyB(ir_node *irn, arm_code_gen_t *cg) {
934         ir_node  *res   = NULL;
935         dbg_info *dbg   = get_irn_dbg_info(irn);
936         ir_mode  *mode  = get_irn_mode(irn);
937         ir_node  *src   = get_CopyB_src(irn);
938         ir_node  *dst   = get_CopyB_dst(irn);
939         ir_node  *mem   = get_CopyB_mem(irn);
940         ir_node  *block = get_nodes_block(irn);
941         int       size  = get_type_size_bytes(get_CopyB_type(irn));
942         ir_graph *irg   = current_ir_graph;
943         ir_node *src_copy;
944         ir_node *dst_copy;
945
946         src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, src);
947         dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, dst);
948
949         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);
950         set_arm_value(res, new_tarval_from_long(size, mode_Iu));
951
952         return res;
953 }
954
955
956
957
958
959 /********************************************
960  *  _                          _
961  * | |                        | |
962  * | |__   ___ _ __   ___   __| | ___  ___
963  * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
964  * | |_) |  __/ | | | (_) | (_| |  __/\__ \
965  * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
966  *
967  ********************************************/
968
969 /**
970  * Return an expanding stack offset.
971  * Note that function is called in the transform phase
972  * where the stack offsets are still relative regarding
973  * the first (frame allocating) IncSP.
974  * However this is exactly what we want because frame
975  * access must be done relative the the fist IncSP ...
976  */
977 static int get_sp_expand_offset(ir_node *inc_sp) {
978         int offset = be_get_IncSP_offset(inc_sp);
979
980         if (offset == BE_STACK_FRAME_SIZE_EXPAND)
981                 return 0;
982
983         return offset;
984 }
985
986 #if 0
987 static ir_node *gen_StackParam(ir_node *irn, arm_code_gen_t *cg) {
988         ir_node   *new_op = NULL;
989         ir_node   *block  = get_nodes_block(irn);
990         ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
991         ir_node   *mem    = new_rd_NoMem(env->irg);
992         ir_node   *ptr    = get_irn_n(irn, 0);
993         ir_entity *ent    = be_get_frame_entity(irn);
994         ir_mode   *mode   = env->mode;
995
996 //      /* If the StackParam has only one user ->     */
997 //      /* put it in the Block where the user resides */
998 //      if (get_irn_n_edges(node) == 1) {
999 //              env->block = get_nodes_block(get_edge_src_irn(get_irn_out_edge_first(node)));
1000 //      }
1001
1002         if (mode_is_float(mode)) {
1003                 if (USE_SSE2(env->cg))
1004                         new_op = new_rd_ia32_fLoad(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1005                 else {
1006                         env->cg->used_x87 = 1;
1007                         new_op = new_rd_ia32_vfld(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1008                 }
1009         }
1010         else {
1011                 new_op = new_rd_ia32_Load(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1012         }
1013
1014         set_ia32_frame_ent(new_op, ent);
1015         set_ia32_use_frame(new_op);
1016
1017         set_ia32_am_support(new_op, ia32_am_Source);
1018         set_ia32_op_type(new_op, ia32_AddrModeS);
1019         set_ia32_am_flavour(new_op, ia32_B);
1020         set_ia32_ls_mode(new_op, mode);
1021
1022         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1023
1024         return new_rd_Proj(env->dbg, env->irg, block, new_op, mode, 0);
1025 }
1026 #endif
1027
1028 /**
1029  * Transforms a FrameAddr into an ia32 Add.
1030  */
1031 static ir_node *gen_be_FrameAddr(ir_node *irn, arm_code_gen_t *cg) {
1032         ir_node *block  = get_nodes_block(irn);
1033         ir_entity *ent  = be_get_frame_entity(irn);
1034         int     offset  = get_entity_offset(ent);
1035         ir_node *op     = get_irn_n(irn, 0);
1036         ir_node *cnst;
1037         ir_mode *mode   = get_irn_mode(irn);
1038         dbg_info *dbg   = get_irn_dbg_info(irn);
1039
1040         if (be_is_IncSP(op)) {
1041                 /* BEWARE: we get an offset which is absolute from an offset that
1042                    is relative. Both must be merged */
1043                 offset += get_sp_expand_offset(op);
1044         }
1045         cnst = create_const_graph_value(irn, block, (unsigned)offset);
1046         if (is_arm_Mov_i(cnst))
1047                 return new_rd_arm_Add_i(dbg, current_ir_graph, block, op, mode, get_arm_value(cnst));
1048         return new_rd_arm_Add(dbg, current_ir_graph, block, op, cnst, mode, ARM_SHF_NONE, NULL);
1049 }
1050
1051 #if 0
1052 /**
1053  * Transforms a FrameLoad into an ia32 Load.
1054  */
1055 static ir_node *gen_FrameLoad(ir_node *irn, arm_code_gen_t *cg) {
1056         ir_node   *new_op = NULL;
1057         ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
1058         ir_node   *mem    = get_irn_n(irn, 0);
1059         ir_node   *ptr    = get_irn_n(irn, 1);
1060         ir_entity *ent    = be_get_frame_entity(irn);
1061         ir_mode   *mode   = get_type_mode(get_entity_type(ent));
1062
1063         if (mode_is_float(mode)) {
1064                 if (USE_SSE2(env->cg))
1065                         new_op = new_rd_ia32_fLoad(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
1066                 else {
1067                         env->cg->used_x87 = 1;
1068                         new_op = new_rd_ia32_vfld(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
1069                 }
1070         }
1071         else {
1072                 new_op = new_rd_ia32_Load(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
1073         }
1074
1075         set_ia32_frame_ent(new_op, ent);
1076         set_ia32_use_frame(new_op);
1077
1078         set_ia32_am_support(new_op, ia32_am_Source);
1079         set_ia32_op_type(new_op, ia32_AddrModeS);
1080         set_ia32_am_flavour(new_op, ia32_B);
1081         set_ia32_ls_mode(new_op, mode);
1082
1083         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1084
1085         return new_op;
1086 }
1087 #endif
1088
1089 #if 0
1090 /**
1091  * Transforms a FrameStore into an ia32 Store.
1092  */
1093 static ir_node *gen_FrameStore(ir_node *irn, arm_code_gen_t *cg) {
1094         ir_node   *new_op = NULL;
1095         ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
1096         ir_node   *mem    = get_irn_n(irn, 0);
1097         ir_node   *ptr    = get_irn_n(irn, 1);
1098         ir_node   *val    = get_irn_n(irn, 2);
1099         ir_entity *ent    = be_get_frame_entity(irn);
1100         ir_mode   *mode   = get_irn_mode(val);
1101
1102         if (mode_is_float(mode)) {
1103                 if (USE_SSE2(env->cg))
1104                         new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1105                 else {
1106                         env->cg->used_x87 = 1;
1107                         new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1108                 }
1109         }
1110         else if (get_mode_size_bits(mode) == 8) {
1111                 new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1112         }
1113         else {
1114                 new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1115         }
1116
1117         set_ia32_frame_ent(new_op, ent);
1118         set_ia32_use_frame(new_op);
1119
1120         set_ia32_am_support(new_op, ia32_am_Dest);
1121         set_ia32_op_type(new_op, ia32_AddrModeD);
1122         set_ia32_am_flavour(new_op, ia32_B);
1123         set_ia32_ls_mode(new_op, mode);
1124
1125         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1126
1127         return new_op;
1128 }
1129 #endif
1130
1131
1132 // static ir_node *gen_be_Copy(ir_node *irn, arm_code_gen_t *cg) {
1133 //      return new_rd_arm_Copy(env->dbg, env->irg, env->block, op, env->mode);
1134 // }
1135
1136 /*********************************************************
1137  *                  _             _      _
1138  *                 (_)           | |    (_)
1139  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
1140  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
1141  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
1142  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
1143  *
1144  *********************************************************/
1145
1146 /**
1147  * move constants out of the start block
1148  */
1149 void arm_move_consts(ir_node *node, void *env) {
1150         int i;
1151
1152         if (is_Block(node))
1153                 return;
1154
1155         if (is_Phi(node)) {
1156                 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
1157                         ir_node *pred = get_irn_n(node,i);
1158                         ir_opcode pred_code = get_irn_opcode(pred);
1159                         if (pred_code == iro_Const) {
1160                                 ir_node *const_graph;
1161                                 const_graph = create_const_graph(pred, get_nodes_block(get_irn_n(get_nodes_block(node),i)));
1162                                 set_irn_n(node, i, const_graph);
1163                         }
1164                         else if (pred_code == iro_SymConst) {
1165                                 /* FIXME: in general, SymConst always require a load, so it
1166                                    might be better to place them into the first real block
1167                                    and let the spiller rematerialize them. */
1168                                 const char *str = get_sc_name(pred);
1169                                 ir_node *symconst_node;
1170                                 symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1171                                         current_ir_graph, get_nodes_block(get_irn_n(get_nodes_block(node),i)),
1172                                         get_irn_mode(pred), str);
1173                                 set_irn_n(node, i, symconst_node);
1174                         }
1175                 }
1176                 return;
1177         }
1178         for (i = 0; i < get_irn_arity(node); i++) {
1179                 ir_node *pred = get_irn_n(node,i);
1180                 ir_opcode pred_code = get_irn_opcode(pred);
1181                 if (pred_code == iro_Const) {
1182                         ir_node *const_graph;
1183                         const_graph = create_const_graph(pred, get_nodes_block(node));
1184                         set_irn_n(node, i, const_graph);
1185                 } else if (pred_code == iro_SymConst) {
1186                         const char *str = get_sc_name(pred);
1187                         ir_node *symconst_node;
1188                         symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1189                                 current_ir_graph, get_nodes_block(node),
1190                                 get_irn_mode(pred), str);
1191                         set_irn_n(node, i, symconst_node);
1192                 }
1193         }
1194 }
1195
1196
1197 /************************************************************************/
1198 /* move symbolic constants out of startblock                            */
1199 /************************************************************************/
1200 void arm_move_symconsts(ir_node *node, void *env) {
1201         int i;
1202
1203         if (is_Block(node))
1204                 return;
1205
1206         for (i = 0; i < get_irn_arity(node); i++) {
1207                 ir_node *pred       = get_irn_n(node,i);
1208                 ir_opcode pred_code = get_irn_opcode(pred);
1209
1210                 if (pred_code == iro_SymConst) {
1211                         const char *str = get_sc_name(pred);
1212                         ir_node    *symconst_node;
1213
1214                         symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1215                                 current_ir_graph, get_nodes_block(node), get_irn_mode(pred), str);
1216                         set_irn_n(node, i, symconst_node);
1217                 }
1218         }
1219 }
1220
1221 /**
1222  * the BAD transformer.
1223  */
1224 static ir_node *bad_transform(ir_node *irn, arm_code_gen_t *cg) {
1225         ir_fprintf(stderr, "Not implemented: %+F\n", irn);
1226         assert(0);
1227         return NULL;
1228 }
1229
1230 /**
1231  * Enters all transform functions into the generic pointer
1232  */
1233 void arm_register_transformers(void) {
1234         ir_op *op_Max, *op_Min, *op_Mulh;
1235
1236         /* first clear the generic function pointer for all ops */
1237         clear_irp_opcodes_generic_func();
1238
1239 #define FIRM_OP(a)     op_##a->ops.generic = (op_func)gen_##a
1240 #define BAD(a)         op_##a->ops.generic = (op_func)bad_transform
1241 #define IGN(a)
1242
1243         FIRM_OP(Add);  // done
1244         FIRM_OP(Mul);  // done
1245         FIRM_OP(Quot); // done
1246         FIRM_OP(And);  // done
1247         FIRM_OP(Or);   // done
1248         FIRM_OP(Eor);  // done
1249
1250         FIRM_OP(Sub);  // done
1251         FIRM_OP(Shl);  // done
1252         FIRM_OP(Shr);  // done
1253         FIRM_OP(Shrs); // done
1254
1255         FIRM_OP(Minus); // done
1256         FIRM_OP(Not);   // done
1257         FIRM_OP(Abs);   // done
1258
1259         FIRM_OP(CopyB); // done
1260         FIRM_OP(Const); // TODO: floating point consts
1261         FIRM_OP(Conv); // TODO: floating point conversions
1262
1263         FIRM_OP(Load);   // done
1264         FIRM_OP(Store);  // done
1265
1266         FIRM_OP(SymConst);
1267         FIRM_OP(Cond);    // integer done
1268
1269         /* TODO: implement these nodes */
1270
1271         IGN(Div);    // intrinsic lowering
1272         IGN(Mod);    // intrinsic lowering
1273         IGN(DivMod); // TODO: implement DivMod
1274
1275         IGN(Mux);
1276         IGN(Unknown);
1277         IGN(Cmp);     // done, implemented in cond
1278
1279         /* You probably don't need to handle the following nodes */
1280
1281         IGN(Call);
1282         IGN(Proj);
1283         IGN(Alloc);
1284
1285         IGN(Block);
1286         IGN(Start);
1287         IGN(End);
1288         IGN(NoMem);
1289         IGN(Phi);
1290         IGN(IJmp);
1291         IGN(Jmp);     // emitter done
1292         IGN(Break);
1293         IGN(Sync);
1294
1295         BAD(Raise);
1296         BAD(Sel);
1297         BAD(InstOf);
1298         BAD(Cast);
1299         BAD(Free);
1300         BAD(Tuple);
1301         BAD(Id);
1302         BAD(Bad);
1303         BAD(Confirm);
1304         BAD(Filter);
1305         BAD(CallBegin);
1306         BAD(EndReg);
1307         BAD(EndExcept);
1308
1309         FIRM_OP(be_FrameAddr);
1310
1311         op_Max = get_op_Max();
1312         if (op_Max)
1313                 BAD(Max);
1314         op_Min = get_op_Min();
1315         if (op_Min)
1316                 BAD(Min);
1317         op_Mulh = get_op_Mulh();
1318         if (op_Mulh)
1319                 BAD(Mulh);
1320
1321 #undef IGN
1322 #undef FIRM_OP
1323 #undef BAD
1324 }
1325
1326 typedef ir_node *(transform_func)(ir_node *irn, arm_code_gen_t *cg);
1327
1328 /**
1329  * Transforms the given firm node (and maybe some other related nodes)
1330  * into one or more assembler nodes.
1331  *
1332  * @param node    the firm node
1333  * @param env     the debug module
1334  */
1335 void arm_transform_node(ir_node *node, void *env) {
1336         arm_code_gen_t *cg = (arm_code_gen_t *)env;
1337         ir_op *op          = get_irn_op(node);
1338         ir_node *asm_node  = NULL;
1339
1340         if (op == op_Block)
1341                 return;
1342
1343         DBG((cg->mod, LEVEL_1, "check %+F ... ", node));
1344
1345         if (op->ops.generic) {
1346                 transform_func *transform = (transform_func *)op->ops.generic;
1347
1348                 asm_node = (*transform)(node, cg);
1349         }
1350
1351         if (asm_node) {
1352                 exchange(node, asm_node);
1353                 DB((cg->mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1354         }
1355         else {
1356                 DB((cg->mod, LEVEL_1, "ignored\n"));
1357         }
1358 }