- further refactoring and finally eliminated the callback for get_out_reg_reqs
[libfirm] / ir / be / arm / arm_transform.c
1 /*
2  * Copyright (C) 1995-2008 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 #include "config.h"
27
28 #include "irnode_t.h"
29 #include "irgraph_t.h"
30 #include "irmode_t.h"
31 #include "irgmod.h"
32 #include "iredges.h"
33 #include "irvrfy.h"
34 #include "ircons.h"
35 #include "irprintf.h"
36 #include "dbginfo.h"
37 #include "iropt_t.h"
38 #include "debug.h"
39 #include "error.h"
40
41 #include "../benode.h"
42 #include "../beirg.h"
43 #include "../beutil.h"
44 #include "../betranshlp.h"
45 #include "bearch_arm_t.h"
46
47 #include "arm_nodes_attr.h"
48 #include "arm_transform.h"
49 #include "arm_optimize.h"
50 #include "arm_new_nodes.h"
51 #include "arm_map_regs.h"
52
53 #include "gen_arm_regalloc_if.h"
54
55 #include <limits.h>
56
57
58 /** hold the current code generator during transformation */
59 static arm_code_gen_t *env_cg;
60
61 extern ir_op *get_op_Mulh(void);
62
63
64 /****************************************************************************************************
65  *                  _        _                        __                           _   _
66  *                 | |      | |                      / _|                         | | (_)
67  *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
68  * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
69  * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
70  * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
71  *
72  ****************************************************************************************************/
73
74 static inline int mode_needs_gp_reg(ir_mode *mode) {
75         return mode_is_int(mode) || mode_is_reference(mode);
76 }
77
78 /**
79  * Creates a arm_Const node.
80  */
81 static ir_node *create_mov_node(dbg_info *dbg, ir_node *block, long value) {
82         ir_mode *mode  = mode_Iu;
83         ir_node *res;
84
85         if (mode_needs_gp_reg(mode))
86                 mode = mode_Iu;
87         res = new_bd_arm_Mov_i(dbg, block, mode, value);
88         be_dep_on_frame(res);
89         return res;
90 }
91
92 /**
93  * Creates a arm_Const_Neg node.
94  */
95 static ir_node *create_mvn_node(dbg_info *dbg, ir_node *block, long value) {
96         ir_mode *mode = mode_Iu;
97         ir_node *res;
98
99         if (mode_needs_gp_reg(mode))
100                 mode = mode_Iu;
101         res = new_bd_arm_Mvn_i(dbg, block, mode, value);
102         be_dep_on_frame(res);
103         return res;
104 }
105
106 #define NEW_BINOP_NODE(opname, env, op1, op2) new_bd_arm_##opname(env->dbg, current_ir_graph, env->block, op1, op2, env->mode)
107
108 /**
109  * Creates a possible DAG for an constant.
110  */
111 static ir_node *create_const_graph_value(dbg_info *dbg, ir_node *block, unsigned int value) {
112         ir_node *result;
113         arm_vals v, vn;
114         int cnt;
115         ir_mode *mode = mode_Iu;
116
117         arm_gen_vals_from_word(value, &v);
118         arm_gen_vals_from_word(~value, &vn);
119
120         if (vn.ops < v.ops) {
121                 /* remove bits */
122                 result = create_mvn_node(dbg, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
123
124                 for (cnt = 1; cnt < vn.ops; ++cnt) {
125                         long value = arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]);
126                         ir_node *bic_i_node = new_bd_arm_Bic_i(dbg, block, result, mode, value);
127                         result = bic_i_node;
128                 }
129         }
130         else {
131                 /* add bits */
132                 result = create_mov_node(dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
133
134                 for (cnt = 1; cnt < v.ops; ++cnt) {
135                         long value = arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]);
136                         ir_node *orr_i_node = new_bd_arm_Or_i(dbg, block, result, mode, value);
137                         result = orr_i_node;
138                 }
139         }
140         return result;
141 }
142
143 /**
144  * Create a DAG constructing a given Const.
145  *
146  * @param irn  a Firm const
147  */
148 static ir_node *create_const_graph(ir_node *irn, ir_node *block) {
149         tarval  *tv = get_Const_tarval(irn);
150         ir_mode *mode = get_tarval_mode(tv);
151         int     value;
152
153         if (mode_is_reference(mode)) {
154                 /* ARM is 32bit, so we can safely convert a reference tarval into Iu */
155                 assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_Iu));
156                 tv = tarval_convert_to(tv, mode_Iu);
157         }
158         value = get_tarval_long(tv);
159         return create_const_graph_value(get_irn_dbg_info(irn), block, value);
160 }
161
162 /**
163  * Create an And that will mask all upper bits
164  */
165 static ir_node *gen_zero_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
166         unsigned mask_bits = (1 << result_bits) - 1;
167         ir_node *mask_node = create_const_graph_value(dbg, block, mask_bits);
168         return new_bd_arm_And(dbg, block, op, mask_node, mode_Iu, ARM_SHF_NONE, 0);
169 }
170
171 /**
172  * Generate code for a sign extension.
173  */
174 static ir_node *gen_sign_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
175         int shift_width = 32 - result_bits;
176         ir_node *shift_const_node = create_const_graph_value(dbg, block, shift_width);
177         ir_node *lshift_node = new_bd_arm_Shl(dbg, block, op, shift_const_node, mode_Iu);
178         ir_node *rshift_node = new_bd_arm_Shrs(dbg, block, lshift_node, shift_const_node, mode_Iu);
179         return rshift_node;
180 }
181
182 /**
183  * Transforms a Conv node.
184  *
185  * @return The created ia32 Conv node
186  */
187 static ir_node *gen_Conv(ir_node *node) {
188         ir_node  *block    = be_transform_node(get_nodes_block(node));
189         ir_node  *op       = get_Conv_op(node);
190         ir_node  *new_op   = be_transform_node(op);
191         ir_mode  *src_mode = get_irn_mode(op);
192         ir_mode  *dst_mode = get_irn_mode(node);
193         dbg_info *dbg      = get_irn_dbg_info(node);
194
195         if (src_mode == dst_mode)
196                 return new_op;
197
198         if (mode_is_float(src_mode) || mode_is_float(dst_mode)) {
199                 env_cg->have_fp_insn = 1;
200
201                 if (USE_FPA(env_cg->isa)) {
202                         if (mode_is_float(src_mode)) {
203                                 if (mode_is_float(dst_mode)) {
204                                         /* from float to float */
205                                         return new_bd_arm_fpaMvf(dbg, block, new_op, dst_mode);
206                                 }
207                                 else {
208                                         /* from float to int */
209                                         return new_bd_arm_fpaFix(dbg, block, new_op, dst_mode);
210                                 }
211                         }
212                         else {
213                                 /* from int to float */
214                                 return new_bd_arm_fpaFlt(dbg, block, new_op, dst_mode);
215                         }
216                 }
217                 else if (USE_VFP(env_cg->isa)) {
218                         panic("VFP not supported yet");
219                         return NULL;
220                 }
221                 else {
222                         panic("Softfloat not supported yet");
223                         return NULL;
224                 }
225         }
226         else { /* complete in gp registers */
227                 int src_bits = get_mode_size_bits(src_mode);
228                 int dst_bits = get_mode_size_bits(dst_mode);
229                 int min_bits;
230                 ir_mode *min_mode;
231
232                 if (is_Load(skip_Proj(op))) {
233                         if (src_bits == dst_bits) {
234                                 /* kill unneccessary conv */
235                                 return new_op;
236                         }
237                         /* after a load, the bit size is already converted */
238                         src_bits = 32;
239                 }
240
241                 if (src_bits == dst_bits) {
242                         /* kill unneccessary conv */
243                         return new_op;
244                 } else if (dst_bits <= 32 && src_bits <= 32) {
245                         if (src_bits < dst_bits) {
246                                 min_bits = src_bits;
247                                 min_mode = src_mode;
248                         } else {
249                                 min_bits = dst_bits;
250                                 min_mode = dst_mode;
251                         }
252                         if (mode_is_signed(min_mode)) {
253                                 return gen_sign_extension(dbg, block, new_op, min_bits);
254                         } else {
255                                 return gen_zero_extension(dbg, block, new_op, min_bits);
256                         }
257                 } else {
258                         panic("Cannot handle Conv %+F->%+F with %d->%d bits", src_mode, dst_mode,
259                                 src_bits, dst_bits);
260                         return NULL;
261                 }
262         }
263 }
264
265 /**
266  * Return true if an operand is a shifter operand
267  */
268 static int is_shifter_operand(ir_node *n, arm_shift_modifier *pmod) {
269         arm_shift_modifier mod = ARM_SHF_NONE;
270
271         if (is_arm_Mov(n))
272                 mod = get_arm_shift_modifier(n);
273
274         *pmod = mod;
275         if (mod != ARM_SHF_NONE) {
276                 long v = get_arm_imm_value(n);
277                 if (v < 32)
278                         return (int)v;
279         }
280         return 0;
281 }
282
283 /**
284  * Creates an ARM Add.
285  *
286  * @return the created arm Add node
287  */
288 static ir_node *gen_Add(ir_node *node) {
289         ir_node  *block   = be_transform_node(get_nodes_block(node));
290         ir_node  *op1     = get_Add_left(node);
291         ir_node  *new_op1 = be_transform_node(op1);
292         ir_node  *op2     = get_Add_right(node);
293         ir_node  *new_op2 = be_transform_node(op2);
294         ir_mode  *mode    = get_irn_mode(node);
295         ir_node  *new_op3;
296         int v;
297         arm_shift_modifier mod;
298         dbg_info *dbg = get_irn_dbg_info(node);
299
300         if (mode_is_float(mode)) {
301                 env_cg->have_fp_insn = 1;
302                 if (USE_FPA(env_cg->isa)) {
303                         if (is_arm_fpaMvf_i(new_op1))
304                                 return new_bd_arm_fpaAdf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
305                         if (is_arm_fpaMvf_i(new_op2))
306                                 return new_bd_arm_fpaAdf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
307                         return new_bd_arm_fpaAdf(dbg, block, new_op1, new_op2, mode);
308                 } else if (USE_VFP(env_cg->isa)) {
309                         assert(mode != mode_E && "IEEE Extended FP not supported");
310                         panic("VFP not supported yet");
311                         return NULL;
312                 }
313                 else {
314                         panic("Softfloat not supported yet");
315                         return NULL;
316                 }
317         } else {
318                 assert(mode_is_data(mode));
319                 mode = mode_Iu;
320
321                 if (is_arm_Mov_i(new_op1))
322                         return new_bd_arm_Add_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
323                 if (is_arm_Mov_i(new_op2))
324                         return new_bd_arm_Add_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
325
326                 /* check for MLA */
327                 if (is_arm_Mul(new_op1) && get_irn_n_edges(op1) == 1) {
328                         new_op3 = new_op2;
329                         new_op2 = get_irn_n(new_op1, 1);
330                         new_op1 = get_irn_n(new_op1, 0);
331
332                         return new_bd_arm_Mla(dbg, block, new_op1, new_op2, new_op3, mode);
333                 }
334                 if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
335                         new_op3 = new_op1;
336                         new_op1 = get_irn_n(new_op2, 0);
337                         new_op2 = get_irn_n(new_op2, 1);
338
339                         return new_bd_arm_Mla(dbg, block, new_op1, new_op2, new_op3, mode);
340                 }
341
342                 /* is the first a shifter */
343                 v = is_shifter_operand(new_op1, &mod);
344                 if (v) {
345                         new_op1 = get_irn_n(new_op1, 0);
346                         return new_bd_arm_Add(dbg, block, new_op2, new_op1, mode, mod, v);
347                 }
348                 /* is the second a shifter */
349                 v = is_shifter_operand(new_op2, &mod);
350                 if (v) {
351                         new_op2 = get_irn_n(new_op2, 0);
352                         return new_bd_arm_Add(dbg, block, new_op1, new_op2, mode, mod, v);
353                 }
354
355                 /* normal ADD */
356                 return new_bd_arm_Add(dbg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
357         }
358 }
359
360 /**
361  * Creates an ARM Mul.
362  *
363  * @return the created arm Mul node
364  */
365 static ir_node *gen_Mul(ir_node *node) {
366         ir_node  *block   = be_transform_node(get_nodes_block(node));
367         ir_node  *op1     = get_Mul_left(node);
368         ir_node  *new_op1 = be_transform_node(op1);
369         ir_node  *op2     = get_Mul_right(node);
370         ir_node  *new_op2 = be_transform_node(op2);
371         ir_mode  *mode    = get_irn_mode(node);
372         dbg_info *dbg     = get_irn_dbg_info(node);
373
374         if (mode_is_float(mode)) {
375                 env_cg->have_fp_insn = 1;
376                 if (USE_FPA(env_cg->isa)) {
377                         if (is_arm_Mov_i(new_op1))
378                                 return new_bd_arm_fpaMuf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
379                         if (is_arm_Mov_i(new_op2))
380                                 return new_bd_arm_fpaMuf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
381                         return new_bd_arm_fpaMuf(dbg, block, new_op1, new_op2, mode);
382                 }
383                 else if (USE_VFP(env_cg->isa)) {
384                         assert(mode != mode_E && "IEEE Extended FP not supported");
385                         panic("VFP not supported yet");
386                         return NULL;
387                 }
388                 else {
389                         panic("Softfloat not supported yet");
390                         return NULL;
391                 }
392         }
393         assert(mode_is_data(mode));
394         mode = mode_Iu;
395         return new_bd_arm_Mul(dbg, block, new_op1, new_op2, mode);
396 }
397
398 /**
399  * Creates an ARM floating point Div.
400  *
401  * @param env   The transformation environment
402  * @return the created arm fDiv node
403  */
404 static ir_node *gen_Quot(ir_node *node) {
405         ir_node  *block   = be_transform_node(get_nodes_block(node));
406         ir_node  *op1     = get_Quot_left(node);
407         ir_node  *new_op1 = be_transform_node(op1);
408         ir_node  *op2     = get_Quot_right(node);
409         ir_node  *new_op2 = be_transform_node(op2);
410         ir_mode  *mode    = get_irn_mode(node);
411         dbg_info *dbg     = get_irn_dbg_info(node);
412
413         assert(mode != mode_E && "IEEE Extended FP not supported");
414
415         env_cg->have_fp_insn = 1;
416         if (USE_FPA(env_cg->isa)) {
417                 if (is_arm_Mov_i(new_op1))
418                         return new_bd_arm_fpaRdf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
419                 if (is_arm_Mov_i(new_op2))
420                         return new_bd_arm_fpaDvf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
421                 return new_bd_arm_fpaDvf(dbg, block, new_op1, new_op2, mode);
422         } else if (USE_VFP(env_cg->isa)) {
423                 assert(mode != mode_E && "IEEE Extended FP not supported");
424                 panic("VFP not supported yet");
425         }
426         else {
427                 panic("Softfloat not supported yet");
428                 return NULL;
429         }
430 }
431
432 #define GEN_INT_OP(op) \
433         ir_node  *block   = be_transform_node(get_nodes_block(node)); \
434         ir_node  *op1     = get_ ## op ## _left(node); \
435         ir_node  *new_op1 = be_transform_node(op1); \
436         ir_node  *op2     = get_ ## op ## _right(node); \
437         ir_node  *new_op2 = be_transform_node(op2); \
438         ir_mode  *mode    = mode_Iu; \
439         dbg_info *dbg     = get_irn_dbg_info(node); \
440         int      v; \
441         arm_shift_modifier mod; \
442  \
443         if (is_arm_Mov_i(new_op1)) \
444                 return new_bd_arm_ ## op ## _i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1)); \
445         if (is_arm_Mov_i(new_op2)) \
446                 return new_bd_arm_ ## op ## _i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2)); \
447         /* is the first a shifter */ \
448         v = is_shifter_operand(new_op1, &mod); \
449         if (v) { \
450                 new_op1 = get_irn_n(new_op1, 0); \
451                 return new_bd_arm_ ## op(dbg, block, new_op2, new_op1, mode, mod, v); \
452         } \
453         /* is the second a shifter */ \
454         v = is_shifter_operand(new_op2, &mod); \
455         if (v) { \
456                 new_op2 = get_irn_n(new_op2, 0); \
457                 return new_bd_arm_ ## op(dbg, block, new_op1, new_op2, mode, mod, v); \
458         } \
459         /* Normal op */ \
460         return new_bd_arm_ ## op(dbg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0) \
461
462 /**
463  * Creates an ARM And.
464  *
465  * @return the created arm And node
466  */
467 static ir_node *gen_And(ir_node *node) {
468         GEN_INT_OP(And);
469 }
470
471 /**
472  * Creates an ARM Orr.
473  *
474  * @param env   The transformation environment
475  * @return the created arm Or node
476  */
477 static ir_node *gen_Or(ir_node *node) {
478         GEN_INT_OP(Or);
479 }
480
481 /**
482  * Creates an ARM Eor.
483  *
484  * @return the created arm Eor node
485  */
486 static ir_node *gen_Eor(ir_node *node) {
487         GEN_INT_OP(Eor);
488 }
489
490 /**
491  * Creates an ARM Sub.
492  *
493  * @return the created arm Sub node
494  */
495 static ir_node *gen_Sub(ir_node *node) {
496         ir_node  *block   = be_transform_node(get_nodes_block(node));
497         ir_node  *op1     = get_Sub_left(node);
498         ir_node  *new_op1 = be_transform_node(op1);
499         ir_node  *op2     = get_Sub_right(node);
500         ir_node  *new_op2 = be_transform_node(op2);
501         ir_mode  *mode    = get_irn_mode(node);
502         dbg_info *dbg     = get_irn_dbg_info(node);
503         int      v;
504         arm_shift_modifier mod;
505
506         if (mode_is_float(mode)) {
507                 env_cg->have_fp_insn = 1;
508                 if (USE_FPA(env_cg->isa)) {
509                         if (is_arm_Mov_i(new_op1))
510                                 return new_bd_arm_fpaRsf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
511                         if (is_arm_Mov_i(new_op2))
512                                 return new_bd_arm_fpaSuf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
513                         return new_bd_arm_fpaSuf(dbg, block, new_op1, new_op2, mode);
514                 } else if (USE_VFP(env_cg->isa)) {
515                         assert(mode != mode_E && "IEEE Extended FP not supported");
516                         panic("VFP not supported yet");
517                         return NULL;
518                 }
519                 else {
520                         panic("Softfloat not supported yet");
521                         return NULL;
522                 }
523         }
524         else {
525                 assert(mode_is_data(mode) && "unknown mode for Sub");
526                 mode = mode_Iu;
527
528                 if (is_arm_Mov_i(new_op1))
529                         return new_bd_arm_Rsb_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
530                 if (is_arm_Mov_i(new_op2))
531                         return new_bd_arm_Sub_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
532
533                 /* is the first a shifter */
534                 v = is_shifter_operand(new_op1, &mod);
535                 if (v) {
536                         new_op1 = get_irn_n(new_op1, 0);
537                         return new_bd_arm_Rsb(dbg, block, new_op2, new_op1, mode, mod, v);
538                 }
539                 /* is the second a shifter */
540                 v = is_shifter_operand(new_op2, &mod);
541                 if (v) {
542                         new_op2 = get_irn_n(new_op2, 0);
543                         return new_bd_arm_Sub(dbg, block, new_op1, new_op2, mode, mod, v);
544                 }
545                 /* normal sub */
546                 return new_bd_arm_Sub(dbg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
547         }
548 }
549
550 /**
551  * Creates an ARM Shl.
552  *
553  * @return the created ARM Shl node
554  */
555 static ir_node *gen_Shl(ir_node *node) {
556         ir_node  *block   = be_transform_node(get_nodes_block(node));
557         ir_node  *op1     = get_Shl_left(node);
558         ir_node  *new_op1 = be_transform_node(op1);
559         ir_node  *op2     = get_Shl_right(node);
560         ir_node  *new_op2 = be_transform_node(op2);
561         ir_mode  *mode    = mode_Iu;
562         dbg_info *dbg     = get_irn_dbg_info(node);
563
564         if (is_arm_Mov_i(new_op2)) {
565                 return new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_LSL, get_arm_imm_value(new_op2));
566         }
567         return new_bd_arm_Shl(dbg, block, new_op1, new_op2, mode);
568 }
569
570 /**
571  * Creates an ARM Shr.
572  *
573  * @return the created ARM Shr node
574  */
575 static ir_node *gen_Shr(ir_node *node) {
576         ir_node  *block   = be_transform_node(get_nodes_block(node));
577         ir_node  *op1     = get_Shr_left(node);
578         ir_node  *new_op1 = be_transform_node(op1);
579         ir_node  *op2     = get_Shr_right(node);
580         ir_node  *new_op2 = be_transform_node(op2);
581         ir_mode  *mode    = mode_Iu;
582         dbg_info *dbg     = get_irn_dbg_info(node);
583
584         if (is_arm_Mov_i(new_op2)) {
585                 return new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_LSR, get_arm_imm_value(new_op2));
586         }
587         return new_bd_arm_Shr(dbg, block, new_op1, new_op2, mode);
588 }
589
590 /**
591  * Creates an ARM Shrs.
592  *
593  * @return the created ARM Shrs node
594  */
595 static ir_node *gen_Shrs(ir_node *node) {
596         ir_node  *block   = be_transform_node(get_nodes_block(node));
597         ir_node  *op1     = get_Shrs_left(node);
598         ir_node  *new_op1 = be_transform_node(op1);
599         ir_node  *op2     = get_Shrs_right(node);
600         ir_node  *new_op2 = be_transform_node(op2);
601         ir_mode  *mode    = mode_Iu;
602         dbg_info *dbg     = get_irn_dbg_info(node);
603
604         if (is_arm_Mov_i(new_op2)) {
605                 return new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_ASR, get_arm_imm_value(new_op2));
606         }
607         return new_bd_arm_Shrs(dbg, block, new_op1, new_op2, mode);
608 }
609
610 /**
611  * Creates an ARM Ror.
612  *
613  * @return the created ARM Ror node
614  */
615 static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2) {
616         ir_node  *block   = be_transform_node(get_nodes_block(node));
617         ir_node  *new_op1 = be_transform_node(op1);
618         ir_node  *new_op2 = be_transform_node(op2);
619         ir_mode  *mode    = mode_Iu;
620         dbg_info *dbg     = get_irn_dbg_info(node);
621
622         if (is_arm_Mov_i(new_op2)) {
623                 return new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_ROR, get_arm_imm_value(new_op2));
624         }
625         return new_bd_arm_Ror(dbg, block, new_op1, new_op2, mode);
626 }
627
628 /**
629  * Creates an ARM Rol.
630  *
631  * @return the created ARM Rol node
632  *
633  * Note: there is no Rol on arm, we have to use Ror
634  */
635 static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2) {
636         ir_node  *block   = be_transform_node(get_nodes_block(node));
637         ir_node  *new_op1 = be_transform_node(op1);
638         ir_mode  *mode    = mode_Iu;
639         dbg_info *dbg     = get_irn_dbg_info(node);
640         ir_node  *new_op2 = be_transform_node(op2);
641
642         new_op2 = new_bd_arm_Rsb_i(dbg, block, new_op2, mode, 32);
643         return new_bd_arm_Ror(dbg, block, new_op1, new_op2, mode);
644 }
645
646 /**
647  * Creates an ARM ROR from a Firm Rotl.
648  *
649  * @return the created ARM Ror node
650  */
651 static ir_node *gen_Rotl(ir_node *node) {
652         ir_node *rotate = NULL;
653         ir_node *op1    = get_Rotl_left(node);
654         ir_node *op2    = get_Rotl_right(node);
655
656         /* Firm has only RotL, so we are looking for a right (op2)
657            operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
658            that means we can create a RotR. */
659
660         if (is_Add(op2)) {
661                 ir_node *right = get_Add_right(op2);
662                 if (is_Const(right)) {
663                         tarval  *tv   = get_Const_tarval(right);
664                         ir_mode *mode = get_irn_mode(node);
665                         long     bits = get_mode_size_bits(mode);
666                         ir_node *left = get_Add_left(op2);
667
668                         if (is_Minus(left) &&
669                             tarval_is_long(tv)          &&
670                             get_tarval_long(tv) == bits &&
671                             bits                == 32)
672                                 rotate = gen_Ror(node, op1, get_Minus_op(left));
673                 }
674         } else if (is_Sub(op2)) {
675                 ir_node *left = get_Sub_left(op2);
676                 if (is_Const(left)) {
677                         tarval  *tv   = get_Const_tarval(left);
678                         ir_mode *mode = get_irn_mode(node);
679                         long     bits = get_mode_size_bits(mode);
680                         ir_node *right = get_Sub_right(op2);
681
682                         if (tarval_is_long(tv)          &&
683                             get_tarval_long(tv) == bits &&
684                             bits                == 32)
685                                 rotate = gen_Ror(node, op1, right);
686                 }
687         } else if (is_Const(op2)) {
688                         tarval  *tv   = get_Const_tarval(op2);
689                         ir_mode *mode = get_irn_mode(node);
690                         long     bits = get_mode_size_bits(mode);
691
692                         if (tarval_is_long(tv) && bits == 32) {
693                                 ir_node  *block   = be_transform_node(get_nodes_block(node));
694                                 ir_node  *new_op1 = be_transform_node(op1);
695                                 ir_mode  *mode    = mode_Iu;
696                                 dbg_info *dbg     = get_irn_dbg_info(node);
697
698                                 bits = (bits - get_tarval_long(tv)) & 31;
699                                 rotate = new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_ROR, bits);
700                         }
701         }
702
703         if (rotate == NULL) {
704                 rotate = gen_Rol(node, op1, op2);
705         }
706
707         return rotate;
708 }
709
710 /**
711  * Transforms a Not node.
712  *
713  * @return the created ARM Not node
714  */
715 static ir_node *gen_Not(ir_node *node) {
716         ir_node  *block   = be_transform_node(get_nodes_block(node));
717         ir_node  *op      = get_Not_op(node);
718         ir_node  *new_op  = be_transform_node(op);
719         dbg_info *dbg     = get_irn_dbg_info(node);
720         ir_mode  *mode    = mode_Iu;
721         arm_shift_modifier mod = ARM_SHF_NONE;
722         int      v        = is_shifter_operand(new_op, &mod);
723
724         if (v) {
725                 new_op = get_irn_n(new_op, 0);
726         }
727         return new_bd_arm_Mvn(dbg, block, new_op, mode, mod, v);
728 }
729
730 /**
731  * Transforms an Abs node.
732  *
733  * @param env   The transformation environment
734  * @return the created ARM Abs node
735  */
736 static ir_node *gen_Abs(ir_node *node) {
737         ir_node  *block   = be_transform_node(get_nodes_block(node));
738         ir_node  *op      = get_Abs_op(node);
739         ir_node  *new_op  = be_transform_node(op);
740         dbg_info *dbg     = get_irn_dbg_info(node);
741         ir_mode  *mode    = get_irn_mode(node);
742
743         if (mode_is_float(mode)) {
744                 env_cg->have_fp_insn = 1;
745                 if (USE_FPA(env_cg->isa))
746                         return new_bd_arm_fpaAbs(dbg, block, new_op, mode);
747                 else if (USE_VFP(env_cg->isa)) {
748                         assert(mode != mode_E && "IEEE Extended FP not supported");
749                         panic("VFP not supported yet");
750                 }
751                 else {
752                         panic("Softfloat not supported yet");
753                 }
754         }
755         assert(mode_is_data(mode));
756         mode = mode_Iu;
757         return new_bd_arm_Abs(dbg, block, new_op, mode);
758 }
759
760 /**
761  * Transforms a Minus node.
762  *
763  * @return the created ARM Minus node
764  */
765 static ir_node *gen_Minus(ir_node *node) {
766         ir_node  *block   = be_transform_node(get_nodes_block(node));
767         ir_node  *op      = get_Minus_op(node);
768         ir_node  *new_op  = be_transform_node(op);
769         dbg_info *dbg     = get_irn_dbg_info(node);
770         ir_mode  *mode    = get_irn_mode(node);
771
772         if (mode_is_float(mode)) {
773                 env_cg->have_fp_insn = 1;
774                 if (USE_FPA(env_cg->isa))
775                         return new_bd_arm_fpaMvf(dbg, block, op, mode);
776                 else if (USE_VFP(env_cg->isa)) {
777                         assert(mode != mode_E && "IEEE Extended FP not supported");
778                         panic("VFP not supported yet");
779                 }
780                 else {
781                         panic("Softfloat not supported yet");
782                 }
783         }
784         assert(mode_is_data(mode));
785         mode = mode_Iu;
786         return new_bd_arm_Rsb_i(dbg, block, new_op, mode, 0);
787 }
788
789 /**
790  * Transforms a Load.
791  *
792  * @return the created ARM Load node
793  */
794 static ir_node *gen_Load(ir_node *node) {
795         ir_node  *block    = be_transform_node(get_nodes_block(node));
796         ir_node  *ptr      = get_Load_ptr(node);
797         ir_node  *new_ptr  = be_transform_node(ptr);
798         ir_node  *mem      = get_Load_mem(node);
799         ir_node  *new_mem  = be_transform_node(mem);
800         ir_mode  *mode     = get_Load_mode(node);
801         dbg_info *dbg      = get_irn_dbg_info(node);
802         ir_node  *new_load = NULL;
803
804         if (mode_is_float(mode)) {
805                 env_cg->have_fp_insn = 1;
806                 if (USE_FPA(env_cg->isa))
807                         new_load = new_bd_arm_fpaLdf(dbg, block, new_ptr, new_mem, mode);
808                 else if (USE_VFP(env_cg->isa)) {
809                         assert(mode != mode_E && "IEEE Extended FP not supported");
810                         panic("VFP not supported yet");
811                 }
812                 else {
813                         panic("Softfloat not supported yet");
814                 }
815         }
816         else {
817                 assert(mode_is_data(mode) && "unsupported mode for Load");
818
819                 if (mode_is_signed(mode)) {
820                         /* sign extended loads */
821                         switch (get_mode_size_bits(mode)) {
822                         case 8:
823                                 new_load = new_bd_arm_Loadbs(dbg, block, new_ptr, new_mem);
824                                 break;
825                         case 16:
826                                 new_load = new_bd_arm_Loadhs(dbg, block, new_ptr, new_mem);
827                                 break;
828                         case 32:
829                                 new_load = new_bd_arm_Load(dbg, block, new_ptr, new_mem);
830                                 break;
831                         default:
832                                 panic("mode size not supported");
833                         }
834                 } else {
835                         /* zero extended loads */
836                         switch (get_mode_size_bits(mode)) {
837                         case 8:
838                                 new_load = new_bd_arm_Loadb(dbg, block, new_ptr, new_mem);
839                                 break;
840                         case 16:
841                                 new_load = new_bd_arm_Loadh(dbg, block, new_ptr, new_mem);
842                                 break;
843                         case 32:
844                                 new_load = new_bd_arm_Load(dbg, block, new_ptr, new_mem);
845                                 break;
846                         default:
847                                 panic("mode size not supported");
848                         }
849                 }
850         }
851         set_irn_pinned(new_load, get_irn_pinned(node));
852
853         /* check for special case: the loaded value might not be used */
854         if (be_get_Proj_for_pn(node, pn_Load_res) == NULL) {
855                 /* add a result proj and a Keep to produce a pseudo use */
856                 ir_node *proj = new_r_Proj(block, new_load, mode_Iu, pn_arm_Load_res);
857                 be_new_Keep(block, 1, &proj);
858         }
859
860         return new_load;
861 }
862
863 /**
864  * Transforms a Store.
865  *
866  * @return the created ARM Store node
867  */
868 static ir_node *gen_Store(ir_node *node) {
869         ir_node  *block    = be_transform_node(get_nodes_block(node));
870         ir_node  *ptr      = get_Store_ptr(node);
871         ir_node  *new_ptr  = be_transform_node(ptr);
872         ir_node  *mem      = get_Store_mem(node);
873         ir_node  *new_mem  = be_transform_node(mem);
874         ir_node  *val      = get_Store_value(node);
875         ir_node  *new_val  = be_transform_node(val);
876         ir_mode  *mode     = get_irn_mode(val);
877         dbg_info *dbg      = get_irn_dbg_info(node);
878         ir_node *new_store = NULL;
879
880         if (mode_is_float(mode)) {
881                 env_cg->have_fp_insn = 1;
882                 if (USE_FPA(env_cg->isa))
883                         new_store = new_bd_arm_fpaStf(dbg, block, new_ptr, new_val, new_mem, mode);
884                 else if (USE_VFP(env_cg->isa)) {
885                         assert(mode != mode_E && "IEEE Extended FP not supported");
886                         panic("VFP not supported yet");
887                 } else {
888                         panic("Softfloat not supported yet");
889                 }
890         } else {
891                 assert(mode_is_data(mode) && "unsupported mode for Store");
892                 switch (get_mode_size_bits(mode)) {
893                 case 8:
894                         new_store = new_bd_arm_Storeb(dbg, block, new_ptr, new_val, new_mem);
895                 case 16:
896                         new_store = new_bd_arm_Storeh(dbg, block, new_ptr, new_val, new_mem);
897                 default:
898                         new_store = new_bd_arm_Store(dbg, block, new_ptr, new_val, new_mem);
899                 }
900         }
901         set_irn_pinned(new_store, get_irn_pinned(node));
902         return new_store;
903 }
904
905 /**
906  * Transforms a Cond.
907  *
908  * @return the created ARM Cond node
909  */
910 static ir_node *gen_Cond(ir_node *node) {
911         ir_node  *block    = be_transform_node(get_nodes_block(node));
912         ir_node  *selector = get_Cond_selector(node);
913         dbg_info *dbg      = get_irn_dbg_info(node);
914         ir_mode  *mode     = get_irn_mode(selector);
915
916         if (mode == mode_b) {
917                 /* an conditional jump */
918                 ir_node *cmp_node = get_Proj_pred(selector);
919                 ir_node *op1      = get_Cmp_left(cmp_node);
920                 ir_node *new_op1  = be_transform_node(op1);
921                 ir_node *op2      = get_Cmp_right(cmp_node);
922
923                 if (mode_is_float(get_irn_mode(op1))) {
924                         ir_node *new_op2  = be_transform_node(op2);
925                         /* floating point compare */
926                         pn_Cmp pnc = get_Proj_proj(selector);
927
928                         if (pnc & pn_Cmp_Uo) {
929                                 /* check for unordered, need cmf */
930                                 return new_bd_arm_fpaCmfBra(dbg, block, new_op1, new_op2, pnc);
931                         }
932                         /* Hmm: use need cmfe */
933                         return new_bd_arm_fpaCmfeBra(dbg, block, new_op1, new_op2, pnc);
934                 } else if (is_Const(op2) && tarval_is_null(get_Const_tarval(op2))) {
935                         /* compare with 0 */
936                         return new_bd_arm_TstBra(dbg, block, new_op1, new_op1, get_Proj_proj(selector));
937                 } else {
938                         /* integer compare */
939                         ir_node *new_op2  = be_transform_node(op2);
940                         return new_bd_arm_CmpBra(dbg, block, new_op1, new_op2, get_Proj_proj(selector));
941                 }
942         } else {
943                 /* SwitchJmp */
944                 ir_node *new_op = be_transform_node(selector);
945                 ir_node *const_graph;
946                 ir_node *sub;
947
948                 ir_node *proj;
949                 const ir_edge_t *edge;
950                 int min = INT_MAX;
951                 int max = INT_MIN;
952                 int translation;
953                 int pn;
954                 int n_projs;
955
956                 foreach_out_edge(node, edge) {
957                         proj = get_edge_src_irn(edge);
958                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
959
960                         pn = get_Proj_proj(proj);
961
962                         min = pn<min ? pn : min;
963                         max = pn>max ? pn : max;
964                 }
965                 translation = min;
966                 n_projs = max - translation + 1;
967
968                 foreach_out_edge(node, edge) {
969                         proj = get_edge_src_irn(edge);
970                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
971
972                         pn = get_Proj_proj(proj) - translation;
973                         set_Proj_proj(proj, pn);
974                 }
975
976                 const_graph = create_const_graph_value(dbg, block, translation);
977                 sub = new_bd_arm_Sub(dbg, block, new_op, const_graph, mode, ARM_SHF_NONE, 0);
978                 return new_bd_arm_SwitchJmp(dbg, block, sub, n_projs, get_Cond_default_proj(node) - translation);
979         }
980 }
981
982 /**
983  * Returns the name of a SymConst.
984  * @param symc  the SymConst
985  * @return name of the SymConst
986  */
987 static ident *get_sc_ident(ir_node *symc) {
988         ir_entity *ent;
989
990         switch (get_SymConst_kind(symc)) {
991                 case symconst_addr_name:
992                         return get_SymConst_name(symc);
993
994                 case symconst_addr_ent:
995                         ent = get_SymConst_entity(symc);
996                         set_entity_backend_marked(ent, 1);
997                         return get_entity_ld_ident(ent);
998
999                 default:
1000                         assert(0 && "Unsupported SymConst");
1001         }
1002
1003         return NULL;
1004 }
1005
1006 static tarval *fpa_imm[3][fpa_max];
1007
1008 /**
1009  * Check, if a floating point tarval is an fpa immediate, i.e.
1010  * one of 0, 1, 2, 3, 4, 5, 10, or 0.5.
1011  */
1012 static int is_fpa_immediate(tarval *tv) {
1013         ir_mode *mode = get_tarval_mode(tv);
1014         int i, j, res = 1;
1015
1016         switch (get_mode_size_bits(mode)) {
1017         case 32:
1018                 i = 0;
1019                 break;
1020         case 64:
1021                 i = 1;
1022                 break;
1023         default:
1024                 i = 2;
1025         }
1026
1027         if (tarval_cmp(tv, get_tarval_null(mode)) & pn_Cmp_Lt) {
1028                 tv = tarval_neg(tv);
1029                 res = -1;
1030         }
1031
1032         for (j = 0; j < fpa_max; ++j) {
1033                 if (tv == fpa_imm[i][j])
1034                         return res * j;
1035         }
1036         return fpa_max;
1037 }
1038
1039 /**
1040  * Transforms a Const node.
1041  *
1042  * @return The transformed ARM node.
1043  */
1044 static ir_node *gen_Const(ir_node *node) {
1045         ir_node  *block = be_transform_node(get_nodes_block(node));
1046         ir_mode *mode = get_irn_mode(node);
1047         dbg_info *dbg = get_irn_dbg_info(node);
1048
1049         if (mode_is_float(mode)) {
1050                 env_cg->have_fp_insn = 1;
1051                 if (USE_FPA(env_cg->isa)) {
1052                         tarval *tv = get_Const_tarval(node);
1053                         int imm = is_fpa_immediate(tv);
1054
1055                         if (imm != fpa_max) {
1056                                 if (imm > 0)
1057                                         node = new_bd_arm_fpaMvf_i(dbg, block, mode, imm);
1058                                 else
1059                                         node = new_bd_arm_fpaMnf_i(dbg, block, mode, -imm);
1060                         } else {
1061                                 node = new_bd_arm_fpaConst(dbg, block, tv);
1062                         }
1063                         be_dep_on_frame(node);
1064                         return node;
1065                 }
1066                 else if (USE_VFP(env_cg->isa)) {
1067                         assert(mode != mode_E && "IEEE Extended FP not supported");
1068                         panic("VFP not supported yet");
1069                 }
1070                 else {
1071                         panic("Softfloat not supported yet");
1072                 }
1073         }
1074         return create_const_graph(node, block);
1075 }
1076
1077 /**
1078  * Transforms a SymConst node.
1079  *
1080  * @return The transformed ARM node.
1081  */
1082 static ir_node *gen_SymConst(ir_node *node) {
1083         ir_node  *block = be_transform_node(get_nodes_block(node));
1084         ir_mode  *mode  = mode_Iu;
1085         dbg_info *dbg   = get_irn_dbg_info(node);
1086         ir_node  *res;
1087
1088         res = new_bd_arm_SymConst(dbg, block, mode, get_sc_ident(node));
1089         be_dep_on_frame(res);
1090         return res;
1091 }
1092
1093 /**
1094  * Transforms a CopyB node.
1095  *
1096  * @return The transformed ARM node.
1097  */
1098 static ir_node *gen_CopyB(ir_node *node) {
1099         ir_node  *block    = be_transform_node(get_nodes_block(node));
1100         ir_node  *src      = get_CopyB_src(node);
1101         ir_node  *new_src  = be_transform_node(src);
1102         ir_node  *dst      = get_CopyB_dst(node);
1103         ir_node  *new_dst  = be_transform_node(dst);
1104         ir_node  *mem      = get_CopyB_mem(node);
1105         ir_node  *new_mem  = be_transform_node(mem);
1106         dbg_info *dbg      = get_irn_dbg_info(node);
1107         int      size      = get_type_size_bytes(get_CopyB_type(node));
1108         ir_node  *src_copy;
1109         ir_node  *dst_copy;
1110
1111         src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], block, new_src);
1112         dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], block, new_dst);
1113
1114         return new_bd_arm_CopyB(dbg, block, dst_copy, src_copy,
1115                         new_bd_arm_EmptyReg(dbg, block, mode_Iu),
1116                         new_bd_arm_EmptyReg(dbg, block, mode_Iu),
1117                         new_bd_arm_EmptyReg(dbg, block, mode_Iu),
1118                         new_mem, size);
1119 }
1120
1121
1122 /********************************************
1123  *  _                          _
1124  * | |                        | |
1125  * | |__   ___ _ __   ___   __| | ___  ___
1126  * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
1127  * | |_) |  __/ | | | (_) | (_| |  __/\__ \
1128  * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
1129  *
1130  ********************************************/
1131
1132 /**
1133  * Return an expanding stack offset.
1134  * Note that function is called in the transform phase
1135  * where the stack offsets are still relative regarding
1136  * the first (frame allocating) IncSP.
1137  * However this is exactly what we want because frame
1138  * access must be done relative the the fist IncSP ...
1139  */
1140 static int get_sp_expand_offset(ir_node *inc_sp) {
1141         int offset = be_get_IncSP_offset(inc_sp);
1142
1143         if (offset == BE_STACK_FRAME_SIZE_EXPAND)
1144                 return 0;
1145
1146         return offset;
1147 }
1148
1149 #if 0
1150 static ir_node *gen_StackParam(ir_node *irn) {
1151         ir_node  *block    = be_transform_node(get_nodes_block(node));
1152         ir_node   *new_op = NULL;
1153         ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
1154         ir_node   *mem    = new_NoMem();
1155         ir_node   *ptr    = get_irn_n(irn, 0);
1156         ir_entity *ent    = be_get_frame_entity(irn);
1157         ir_mode   *mode   = env->mode;
1158
1159 //      /* If the StackParam has only one user ->     */
1160 //      /* put it in the Block where the user resides */
1161 //      if (get_irn_n_edges(node) == 1) {
1162 //              env->block = get_nodes_block(get_edge_src_irn(get_irn_out_edge_first(node)));
1163 //      }
1164
1165         if (mode_is_float(mode)) {
1166                 if (USE_SSE2(env->cg))
1167                         new_op = new_rd_ia32_fLoad(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1168                 else {
1169                         env->cg->used_x87 = 1;
1170                         new_op = new_rd_ia32_vfld(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1171                 }
1172         }
1173         else {
1174                 new_op = new_rd_ia32_Load(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1175         }
1176
1177         set_ia32_frame_ent(new_op, ent);
1178         set_ia32_use_frame(new_op);
1179
1180         set_ia32_am_support(new_op, ia32_am_Source);
1181         set_ia32_op_type(new_op, ia32_AddrModeS);
1182         set_ia32_am_flavour(new_op, ia32_B);
1183         set_ia32_ls_mode(new_op, mode);
1184
1185         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1186
1187         return new_rd_Proj(env->dbg, env->irg, block, new_op, mode, 0);
1188 }
1189 #endif
1190
1191 /**
1192  * Transforms a FrameAddr into an ARM Add.
1193  */
1194 static ir_node *gen_be_FrameAddr(ir_node *node) {
1195         ir_node   *block  = be_transform_node(get_nodes_block(node));
1196         ir_entity *ent    = be_get_frame_entity(node);
1197         int       offset  = get_entity_offset(ent);
1198         ir_node   *op     = be_get_FrameAddr_frame(node);
1199         ir_node   *new_op = be_transform_node(op);
1200         dbg_info  *dbg    = get_irn_dbg_info(node);
1201         ir_mode   *mode   = mode_Iu;
1202         ir_node   *cnst;
1203
1204         if (be_is_IncSP(op)) {
1205                 /* BEWARE: we get an offset which is absolute from an offset that
1206                    is relative. Both must be merged */
1207                 offset += get_sp_expand_offset(op);
1208         }
1209         cnst = create_const_graph_value(dbg, block, (unsigned)offset);
1210         if (is_arm_Mov_i(cnst))
1211                 return new_bd_arm_Add_i(dbg, block, new_op, mode, get_arm_imm_value(cnst));
1212         return new_bd_arm_Add(dbg, block, new_op, cnst, mode, ARM_SHF_NONE, 0);
1213 }
1214
1215 /**
1216  * Transform a be_AddSP into an arm_AddSP. Eat up const sizes.
1217  */
1218 static ir_node *gen_be_AddSP(ir_node *node) {
1219         ir_node  *block  = be_transform_node(get_nodes_block(node));
1220         ir_node  *sz     = get_irn_n(node, be_pos_AddSP_size);
1221         ir_node  *new_sz = be_transform_node(sz);
1222         ir_node  *sp     = get_irn_n(node, be_pos_AddSP_old_sp);
1223         ir_node  *new_sp = be_transform_node(sp);
1224         dbg_info *dbgi   = get_irn_dbg_info(node);
1225         ir_node  *nomem  = new_NoMem();
1226         ir_node  *new_op;
1227
1228         /* ARM stack grows in reverse direction, make a SubSPandCopy */
1229         new_op = new_bd_arm_SubSPandCopy(dbgi, block, new_sp, new_sz, nomem);
1230
1231         return new_op;
1232 }
1233
1234 /**
1235  * Transform a be_SubSP into an arm_SubSP. Eat up const sizes.
1236  */
1237 static ir_node *gen_be_SubSP(ir_node *node) {
1238         ir_node  *block  = be_transform_node(get_nodes_block(node));
1239         ir_node  *sz     = get_irn_n(node, be_pos_SubSP_size);
1240         ir_node  *new_sz = be_transform_node(sz);
1241         ir_node  *sp     = get_irn_n(node, be_pos_SubSP_old_sp);
1242         ir_node  *new_sp = be_transform_node(sp);
1243         dbg_info *dbgi   = get_irn_dbg_info(node);
1244         ir_node  *nomem  = new_NoMem();
1245         ir_node  *new_op;
1246
1247         /* ARM stack grows in reverse direction, make an AddSP */
1248         new_op = new_bd_arm_AddSP(dbgi, block, new_sp, new_sz, nomem);
1249
1250         return new_op;
1251 }
1252
1253 /**
1254  * Transform a be_Copy.
1255  */
1256 static ir_node *gen_be_Copy(ir_node *node) {
1257         ir_node *result = be_duplicate_node(node);
1258         ir_mode *mode   = get_irn_mode(result);
1259
1260         if (mode_needs_gp_reg(mode)) {
1261                 set_irn_mode(node, mode_Iu);
1262         }
1263
1264         return result;
1265 }
1266
1267 /**
1268  * Transform a Proj from a Load.
1269  */
1270 static ir_node *gen_Proj_Load(ir_node *node) {
1271         ir_node  *block    = be_transform_node(get_nodes_block(node));
1272         ir_node  *load     = get_Proj_pred(node);
1273         ir_node  *new_load = be_transform_node(load);
1274         dbg_info *dbgi     = get_irn_dbg_info(node);
1275         long     proj      = get_Proj_proj(node);
1276
1277         /* renumber the proj */
1278         switch (get_arm_irn_opcode(new_load)) {
1279         case iro_arm_Load:
1280         case iro_arm_Loadb:
1281         case iro_arm_Loadbs:
1282         case iro_arm_Loadh:
1283         case iro_arm_Loadhs:
1284                 /* handle all gp loads equal: they have the same proj numbers. */
1285                 if (proj == pn_Load_res) {
1286                         return new_rd_Proj(dbgi, block, new_load, mode_Iu, pn_arm_Load_res);
1287                 } else if (proj == pn_Load_M) {
1288                         return new_rd_Proj(dbgi, block, new_load, mode_M, pn_arm_Load_M);
1289                 }
1290                 break;
1291         case iro_arm_fpaLdf:
1292                 if (proj == pn_Load_res) {
1293                         ir_mode *mode = get_Load_mode(load);
1294                         return new_rd_Proj(dbgi, block, new_load, mode, pn_arm_fpaLdf_res);
1295                 } else if (proj == pn_Load_M) {
1296                         return new_rd_Proj(dbgi, block, new_load, mode_M, pn_arm_fpaLdf_M);
1297                 }
1298                 break;
1299         default:
1300                 break;
1301         }
1302         panic("Unsupported Proj from Load");
1303 }
1304
1305 /**
1306  * Transform and renumber the Projs from a CopyB.
1307  */
1308 static ir_node *gen_Proj_CopyB(ir_node *node) {
1309         ir_node  *block    = be_transform_node(get_nodes_block(node));
1310         ir_node  *pred     = get_Proj_pred(node);
1311         ir_node  *new_pred = be_transform_node(pred);
1312         dbg_info *dbgi     = get_irn_dbg_info(node);
1313         long     proj      = get_Proj_proj(node);
1314
1315         switch(proj) {
1316         case pn_CopyB_M_regular:
1317                 if (is_arm_CopyB(new_pred)) {
1318                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_CopyB_M);
1319                 }
1320                 break;
1321         default:
1322                 break;
1323         }
1324         panic("Unsupported Proj from CopyB");
1325 }
1326
1327 /**
1328  * Transform and renumber the Projs from a Quot.
1329  */
1330 static ir_node *gen_Proj_Quot(ir_node *node) {
1331         ir_node  *block    = be_transform_node(get_nodes_block(node));
1332         ir_node  *pred     = get_Proj_pred(node);
1333         ir_node  *new_pred = be_transform_node(pred);
1334         dbg_info *dbgi     = get_irn_dbg_info(node);
1335         ir_mode  *mode     = get_irn_mode(node);
1336         long     proj      = get_Proj_proj(node);
1337
1338         switch (proj) {
1339         case pn_Quot_M:
1340                 if (is_arm_fpaDvf(new_pred) || is_arm_fpaDvf_i(new_pred)) {
1341                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaDvf_M);
1342                 } else if (is_arm_fpaRdf(new_pred) || is_arm_fpaRdf_i(new_pred)) {
1343                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaRdf_M);
1344                 } else if (is_arm_fpaFdv(new_pred) || is_arm_fpaFdv_i(new_pred)) {
1345                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaFdv_M);
1346                 } else if (is_arm_fpaFrd(new_pred) || is_arm_fpaFrd_i(new_pred)) {
1347                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaFrd_M);
1348                 }
1349                 break;
1350         case pn_Quot_res:
1351                 if (is_arm_fpaDvf(new_pred) || is_arm_fpaDvf_i(new_pred)) {
1352                         return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaDvf_res);
1353                 } else if (is_arm_fpaRdf(new_pred) || is_arm_fpaRdf_i(new_pred)) {
1354                         return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaRdf_res);
1355                 } else if (is_arm_fpaFdv(new_pred) || is_arm_fpaFdv_i(new_pred)) {
1356                         return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaFdv_res);
1357                 } else if (is_arm_fpaFrd(new_pred) || is_arm_fpaFrd_i(new_pred)) {
1358                         return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaFrd_res);
1359                 }
1360                 break;
1361         default:
1362                 break;
1363         }
1364         panic("Unsupported Proj from Quot");
1365 }
1366
1367 /**
1368  * Transform the Projs of a be_AddSP.
1369  */
1370 static ir_node *gen_Proj_be_AddSP(ir_node *node) {
1371         ir_node  *block    = be_transform_node(get_nodes_block(node));
1372         ir_node  *pred     = get_Proj_pred(node);
1373         ir_node  *new_pred = be_transform_node(pred);
1374         dbg_info *dbgi     = get_irn_dbg_info(node);
1375         long     proj      = get_Proj_proj(node);
1376
1377         if (proj == pn_be_AddSP_sp) {
1378                 ir_node *res = new_rd_Proj(dbgi, block, new_pred, mode_Iu,
1379                                            pn_arm_SubSPandCopy_stack);
1380                 arch_set_irn_register(res, &arm_gp_regs[REG_SP]);
1381                 return res;
1382         } else if(proj == pn_be_AddSP_res) {
1383                 return new_rd_Proj(dbgi, block, new_pred, mode_Iu, pn_arm_SubSPandCopy_addr);
1384         } else if (proj == pn_be_AddSP_M) {
1385                 return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_SubSPandCopy_M);
1386         }
1387         panic("Unsupported Proj from AddSP");
1388 }
1389
1390 /**
1391  * Transform the Projs of a be_SubSP.
1392  */
1393 static ir_node *gen_Proj_be_SubSP(ir_node *node) {
1394         ir_node  *block    = be_transform_node(get_nodes_block(node));
1395         ir_node  *pred     = get_Proj_pred(node);
1396         ir_node  *new_pred = be_transform_node(pred);
1397         dbg_info *dbgi     = get_irn_dbg_info(node);
1398         long     proj      = get_Proj_proj(node);
1399
1400         if (proj == pn_be_SubSP_sp) {
1401                 ir_node *res = new_rd_Proj(dbgi, block, new_pred, mode_Iu,
1402                                            pn_arm_AddSP_stack);
1403                 arch_set_irn_register(res, &arm_gp_regs[REG_SP]);
1404                 return res;
1405         } else if (proj == pn_be_SubSP_M) {
1406                 return new_rd_Proj(dbgi,  block, new_pred, mode_M, pn_arm_AddSP_M);
1407         }
1408         panic("Unsupported Proj from SubSP");
1409 }
1410
1411 /**
1412  * Transform the Projs from a Cmp.
1413  */
1414 static ir_node *gen_Proj_Cmp(ir_node *node) {
1415         (void) node;
1416         panic("Mux NYI");
1417 }
1418
1419
1420 /**
1421  * Transform the Thread Local Storage Proj.
1422  */
1423 static ir_node *gen_Proj_tls(ir_node *node) {
1424         ir_node  *block = be_transform_node(get_nodes_block(node));
1425         dbg_info *dbgi  = NULL;
1426
1427         return new_bd_arm_LdTls(dbgi, block, mode_Iu);
1428 }
1429
1430 /**
1431  * Transform a Proj node.
1432  */
1433 static ir_node *gen_Proj(ir_node *node) {
1434         ir_graph *irg  = current_ir_graph;
1435         dbg_info *dbgi = get_irn_dbg_info(node);
1436         ir_node  *pred = get_Proj_pred(node);
1437         long     proj  = get_Proj_proj(node);
1438
1439         if (is_Store(pred)) {
1440                 if (proj == pn_Store_M) {
1441                         return be_transform_node(pred);
1442                 } else {
1443                         panic("Unsupported Proj from Store");
1444                 }
1445         } else if (is_Load(pred)) {
1446                 return gen_Proj_Load(node);
1447         } else if (is_CopyB(pred)) {
1448                 return gen_Proj_CopyB(node);
1449         } else if (is_Quot(pred)) {
1450                 return gen_Proj_Quot(node);
1451         } else if (be_is_SubSP(pred)) {
1452                 return gen_Proj_be_SubSP(node);
1453         } else if (be_is_AddSP(pred)) {
1454                 return gen_Proj_be_AddSP(node);
1455         } else if (is_Cmp(pred)) {
1456                 return gen_Proj_Cmp(node);
1457         } else if (is_Start(pred)) {
1458                 if (proj == pn_Start_X_initial_exec) {
1459                         ir_node *block = get_nodes_block(pred);
1460                         ir_node *jump;
1461
1462                         /* we exchange the ProjX with a jump */
1463                         block = be_transform_node(block);
1464                         jump  = new_rd_Jmp(dbgi, block);
1465                         return jump;
1466                 }
1467                 if (node == get_irg_anchor(irg, anchor_tls)) {
1468                         return gen_Proj_tls(node);
1469                 }
1470         } else {
1471                 ir_node *new_pred = be_transform_node(pred);
1472                 ir_mode *mode     = get_irn_mode(node);
1473                 if (mode_needs_gp_reg(mode)) {
1474                         ir_node *block    = be_transform_node(get_nodes_block(node));
1475                         ir_node *new_proj = new_r_Proj(block, new_pred, mode_Iu,
1476                                                        get_Proj_proj(node));
1477                         new_proj->node_nr = node->node_nr;
1478                         return new_proj;
1479                 }
1480         }
1481
1482         return be_duplicate_node(node);
1483 }
1484
1485 typedef ir_node *(*create_const_node_func)(dbg_info *db, ir_node *block);
1486
1487 static inline ir_node *create_const(ir_node **place,
1488                                     create_const_node_func func,
1489                                     const arch_register_t* reg)
1490 {
1491         ir_node *block, *res;
1492
1493         if (*place != NULL)
1494                 return *place;
1495
1496         block = get_irg_start_block(env_cg->irg);
1497         res = func(NULL, block);
1498         arch_set_irn_register(res, reg);
1499         *place = res;
1500         return res;
1501 }
1502
1503 static ir_node *arm_new_Unknown_gp(void) {
1504         return create_const(&env_cg->unknown_gp, new_bd_arm_Unknown_GP,
1505                             &arm_gp_regs[REG_GP_UKNWN]);
1506 }
1507
1508 static ir_node *arm_new_Unknown_fpa(void) {
1509         return create_const(&env_cg->unknown_fpa, new_bd_arm_Unknown_FPA,
1510                             &arm_fpa_regs[REG_FPA_UKNWN]);
1511 }
1512
1513 /**
1514  * This function just sets the register for the Unknown node
1515  * as this is not done during register allocation because Unknown
1516  * is an "ignore" node.
1517  */
1518 static ir_node *gen_Unknown(ir_node *node) {
1519         ir_mode *mode = get_irn_mode(node);
1520         if (mode_is_float(mode)) {
1521                 if (USE_FPA(env_cg->isa))
1522                         return arm_new_Unknown_fpa();
1523                 else if (USE_VFP(env_cg->isa))
1524                         panic("VFP not supported yet");
1525                 else
1526                         panic("Softfloat not supported yet");
1527         } else if (mode_needs_gp_reg(mode)) {
1528                 return arm_new_Unknown_gp();
1529         } else {
1530                 assert(0 && "unsupported Unknown-Mode");
1531         }
1532
1533         return NULL;
1534 }
1535
1536 /**
1537  * Change some phi modes
1538  */
1539 static ir_node *gen_Phi(ir_node *node) {
1540         ir_node  *block = be_transform_node(get_nodes_block(node));
1541         ir_graph *irg   = current_ir_graph;
1542         dbg_info *dbgi  = get_irn_dbg_info(node);
1543         ir_mode  *mode  = get_irn_mode(node);
1544         ir_node  *phi;
1545
1546         if (mode_needs_gp_reg(mode)) {
1547                 /* we shouldn't have any 64bit stuff around anymore */
1548                 assert(get_mode_size_bits(mode) <= 32);
1549                 /* all integer operations are on 32bit registers now */
1550                 mode = mode_Iu;
1551         }
1552
1553         /* phi nodes allow loops, so we use the old arguments for now
1554          * and fix this later */
1555         phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node), get_irn_in(node) + 1);
1556         copy_node_attr(node, phi);
1557         be_duplicate_deps(node, phi);
1558
1559         be_enqueue_preds(node);
1560
1561         return phi;
1562 }
1563
1564 /*********************************************************
1565  *                  _             _      _
1566  *                 (_)           | |    (_)
1567  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
1568  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
1569  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
1570  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
1571  *
1572  *********************************************************/
1573
1574 /**
1575  * the BAD transformer.
1576  */
1577 static ir_node *bad_transform(ir_node *irn) {
1578         panic("ARM backend: Not implemented: %+F", irn);
1579         return irn;
1580 }
1581
1582 /**
1583  * Set a node emitter. Make it a bit more type safe.
1584  */
1585 static inline void set_transformer(ir_op *op, be_transform_func arm_transform_func) {
1586         op->ops.generic = (op_func)arm_transform_func;
1587 }
1588
1589 /**
1590  * Enters all transform functions into the generic pointer
1591  */
1592 static void arm_register_transformers(void) {
1593         /* first clear the generic function pointer for all ops */
1594         clear_irp_opcodes_generic_func();
1595
1596 #define GEN(a)     set_transformer(op_##a, gen_##a)
1597 #define BAD(a)     set_transformer(op_##a, bad_transform)
1598
1599         GEN(Add);
1600         GEN(Sub);
1601         GEN(Mul);
1602         BAD(Mulh);      /* unsupported yet */
1603         GEN(And);
1604         GEN(Or);
1605         GEN(Eor);
1606
1607         GEN(Shl);
1608         GEN(Shr);
1609         GEN(Shrs);
1610         GEN(Rotl);
1611
1612         GEN(Quot);
1613
1614         /* should be lowered */
1615         BAD(Div);
1616         BAD(Mod);
1617         BAD(DivMod);
1618
1619         GEN(Minus);
1620         GEN(Conv);
1621         GEN(Abs);
1622         GEN(Not);
1623
1624         GEN(Load);
1625         GEN(Store);
1626         GEN(Cond);
1627
1628         BAD(ASM);       /* unsupported yet */
1629         GEN(CopyB);
1630         BAD(Mux);       /* unsupported yet */
1631         GEN(Proj);
1632         GEN(Phi);
1633
1634         GEN(Const);
1635         GEN(SymConst);
1636
1637         /* we should never see these nodes */
1638         BAD(Raise);
1639         BAD(Sel);
1640         BAD(InstOf);
1641         BAD(Cast);
1642         BAD(Free);
1643         BAD(Tuple);
1644         BAD(Id);
1645         //BAD(Bad);
1646         BAD(Confirm);
1647         BAD(Filter);
1648         BAD(CallBegin);
1649         BAD(EndReg);
1650         BAD(EndExcept);
1651
1652         /* handle builtins */
1653         BAD(Builtin);
1654
1655         /* handle generic backend nodes */
1656         GEN(be_FrameAddr);
1657         //GEN(be_Call);
1658         //GEN(be_Return);
1659         GEN(be_AddSP);
1660         GEN(be_SubSP);
1661         GEN(be_Copy);
1662
1663         /* set the register for all Unknown nodes */
1664         GEN(Unknown);
1665
1666 #undef GEN
1667 #undef BAD
1668 }
1669
1670 /**
1671  * Pre-transform all unknown nodes.
1672  */
1673 static void arm_pretransform_node(void)
1674 {
1675         arm_code_gen_t *cg = env_cg;
1676
1677         cg->unknown_gp  = be_pre_transform_node(cg->unknown_gp);
1678         cg->unknown_fpa = be_pre_transform_node(cg->unknown_fpa);
1679 }
1680
1681 /**
1682  * Initialize fpa Immediate support.
1683  */
1684 static void arm_init_fpa_immediate(void) {
1685         /* 0, 1, 2, 3, 4, 5, 10, or 0.5. */
1686         fpa_imm[0][fpa_null]  = get_tarval_null(mode_F);
1687         fpa_imm[0][fpa_one]   = get_tarval_one(mode_F);
1688         fpa_imm[0][fpa_two]   = new_tarval_from_str("2", 1, mode_F);
1689         fpa_imm[0][fpa_three] = new_tarval_from_str("3", 1, mode_F);
1690         fpa_imm[0][fpa_four]  = new_tarval_from_str("4", 1, mode_F);
1691         fpa_imm[0][fpa_five]  = new_tarval_from_str("5", 1, mode_F);
1692         fpa_imm[0][fpa_ten]   = new_tarval_from_str("10", 2, mode_F);
1693         fpa_imm[0][fpa_half]  = new_tarval_from_str("0.5", 3, mode_F);
1694
1695         fpa_imm[1][fpa_null]  = get_tarval_null(mode_D);
1696         fpa_imm[1][fpa_one]   = get_tarval_one(mode_D);
1697         fpa_imm[1][fpa_two]   = new_tarval_from_str("2", 1, mode_D);
1698         fpa_imm[1][fpa_three] = new_tarval_from_str("3", 1, mode_D);
1699         fpa_imm[1][fpa_four]  = new_tarval_from_str("4", 1, mode_D);
1700         fpa_imm[1][fpa_five]  = new_tarval_from_str("5", 1, mode_D);
1701         fpa_imm[1][fpa_ten]   = new_tarval_from_str("10", 2, mode_D);
1702         fpa_imm[1][fpa_half]  = new_tarval_from_str("0.5", 3, mode_D);
1703
1704         fpa_imm[2][fpa_null]  = get_tarval_null(mode_E);
1705         fpa_imm[2][fpa_one]   = get_tarval_one(mode_E);
1706         fpa_imm[2][fpa_two]   = new_tarval_from_str("2", 1, mode_E);
1707         fpa_imm[2][fpa_three] = new_tarval_from_str("3", 1, mode_E);
1708         fpa_imm[2][fpa_four]  = new_tarval_from_str("4", 1, mode_E);
1709         fpa_imm[2][fpa_five]  = new_tarval_from_str("5", 1, mode_E);
1710         fpa_imm[2][fpa_ten]   = new_tarval_from_str("10", 2, mode_E);
1711         fpa_imm[2][fpa_half]  = new_tarval_from_str("0.5", 3, mode_E);
1712 }
1713
1714 /**
1715  * Transform a Firm graph into an ARM graph.
1716  */
1717 void arm_transform_graph(arm_code_gen_t *cg) {
1718         static int imm_initialized = 0;
1719
1720         if (! imm_initialized) {
1721                 arm_init_fpa_immediate();
1722                 imm_initialized = 1;
1723         }
1724         arm_register_transformers();
1725         env_cg = cg;
1726         be_transform_graph(cg->birg, arm_pretransform_node);
1727 }
1728
1729 void arm_init_transform(void) {
1730         // FIRM_DBG_REGISTER(dbg, "firm.be.arm.transform");
1731 }