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