cb4dda859a7721f7186c8851526df5c520532f31
[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_t.h"
42 #include "../beirg_t.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                 ir_graph *irg = current_ir_graph;
856
857                 /* add a result proj and a Keep to produce a pseudo use */
858                 ir_node *proj = new_r_Proj(block, new_load, mode_Iu, pn_arm_Load_res);
859                 be_new_Keep(arch_get_irn_reg_class_out(proj), block, 1, &proj);
860         }
861
862         return new_load;
863 }
864
865 /**
866  * Transforms a Store.
867  *
868  * @return the created ARM Store node
869  */
870 static ir_node *gen_Store(ir_node *node) {
871         ir_node  *block    = be_transform_node(get_nodes_block(node));
872         ir_node  *ptr      = get_Store_ptr(node);
873         ir_node  *new_ptr  = be_transform_node(ptr);
874         ir_node  *mem      = get_Store_mem(node);
875         ir_node  *new_mem  = be_transform_node(mem);
876         ir_node  *val      = get_Store_value(node);
877         ir_node  *new_val  = be_transform_node(val);
878         ir_mode  *mode     = get_irn_mode(val);
879         dbg_info *dbg      = get_irn_dbg_info(node);
880         ir_node *new_store = NULL;
881
882         if (mode_is_float(mode)) {
883                 env_cg->have_fp_insn = 1;
884                 if (USE_FPA(env_cg->isa))
885                         new_store = new_bd_arm_fpaStf(dbg, block, new_ptr, new_val, new_mem, mode);
886                 else if (USE_VFP(env_cg->isa)) {
887                         assert(mode != mode_E && "IEEE Extended FP not supported");
888                         panic("VFP not supported yet");
889                 } else {
890                         panic("Softfloat not supported yet");
891                 }
892         } else {
893                 assert(mode_is_data(mode) && "unsupported mode for Store");
894                 switch (get_mode_size_bits(mode)) {
895                 case 8:
896                         new_store = new_bd_arm_Storeb(dbg, block, new_ptr, new_val, new_mem);
897                 case 16:
898                         new_store = new_bd_arm_Storeh(dbg, block, new_ptr, new_val, new_mem);
899                 default:
900                         new_store = new_bd_arm_Store(dbg, block, new_ptr, new_val, new_mem);
901                 }
902         }
903         set_irn_pinned(new_store, get_irn_pinned(node));
904         return new_store;
905 }
906
907 /**
908  * Transforms a Cond.
909  *
910  * @return the created ARM Cond node
911  */
912 static ir_node *gen_Cond(ir_node *node) {
913         ir_node  *block    = be_transform_node(get_nodes_block(node));
914         ir_node  *selector = get_Cond_selector(node);
915         dbg_info *dbg      = get_irn_dbg_info(node);
916         ir_mode  *mode     = get_irn_mode(selector);
917
918         if (mode == mode_b) {
919                 /* an conditional jump */
920                 ir_node *cmp_node = get_Proj_pred(selector);
921                 ir_node *op1      = get_Cmp_left(cmp_node);
922                 ir_node *new_op1  = be_transform_node(op1);
923                 ir_node *op2      = get_Cmp_right(cmp_node);
924
925                 if (mode_is_float(get_irn_mode(op1))) {
926                         ir_node *new_op2  = be_transform_node(op2);
927                         /* floating point compare */
928                         pn_Cmp pnc = get_Proj_proj(selector);
929
930                         if (pnc & pn_Cmp_Uo) {
931                                 /* check for unordered, need cmf */
932                                 return new_bd_arm_fpaCmfBra(dbg, block, new_op1, new_op2, pnc);
933                         }
934                         /* Hmm: use need cmfe */
935                         return new_bd_arm_fpaCmfeBra(dbg, block, new_op1, new_op2, pnc);
936                 } else if (is_Const(op2) && tarval_is_null(get_Const_tarval(op2))) {
937                         /* compare with 0 */
938                         return new_bd_arm_TstBra(dbg, block, new_op1, new_op1, get_Proj_proj(selector));
939                 } else {
940                         /* integer compare */
941                         ir_node *new_op2  = be_transform_node(op2);
942                         return new_bd_arm_CmpBra(dbg, block, new_op1, new_op2, get_Proj_proj(selector));
943                 }
944         } else {
945                 /* SwitchJmp */
946                 ir_node *new_op = be_transform_node(selector);
947                 ir_node *const_graph;
948                 ir_node *sub;
949
950                 ir_node *proj;
951                 const ir_edge_t *edge;
952                 int min = INT_MAX;
953                 int max = INT_MIN;
954                 int translation;
955                 int pn;
956                 int n_projs;
957
958                 foreach_out_edge(node, edge) {
959                         proj = get_edge_src_irn(edge);
960                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
961
962                         pn = get_Proj_proj(proj);
963
964                         min = pn<min ? pn : min;
965                         max = pn>max ? pn : max;
966                 }
967                 translation = min;
968                 n_projs = max - translation + 1;
969
970                 foreach_out_edge(node, edge) {
971                         proj = get_edge_src_irn(edge);
972                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
973
974                         pn = get_Proj_proj(proj) - translation;
975                         set_Proj_proj(proj, pn);
976                 }
977
978                 const_graph = create_const_graph_value(dbg, block, translation);
979                 sub = new_bd_arm_Sub(dbg, block, new_op, const_graph, mode, ARM_SHF_NONE, 0);
980                 return new_bd_arm_SwitchJmp(dbg, block, sub, n_projs, get_Cond_default_proj(node) - translation);
981         }
982 }
983
984 /**
985  * Returns the name of a SymConst.
986  * @param symc  the SymConst
987  * @return name of the SymConst
988  */
989 static ident *get_sc_ident(ir_node *symc) {
990         ir_entity *ent;
991
992         switch (get_SymConst_kind(symc)) {
993                 case symconst_addr_name:
994                         return get_SymConst_name(symc);
995
996                 case symconst_addr_ent:
997                         ent = get_SymConst_entity(symc);
998                         set_entity_backend_marked(ent, 1);
999                         return get_entity_ld_ident(ent);
1000
1001                 default:
1002                         assert(0 && "Unsupported SymConst");
1003         }
1004
1005         return NULL;
1006 }
1007
1008 static tarval *fpa_imm[3][fpa_max];
1009
1010 /**
1011  * Check, if a floating point tarval is an fpa immediate, i.e.
1012  * one of 0, 1, 2, 3, 4, 5, 10, or 0.5.
1013  */
1014 static int is_fpa_immediate(tarval *tv) {
1015         ir_mode *mode = get_tarval_mode(tv);
1016         int i, j, res = 1;
1017
1018         switch (get_mode_size_bits(mode)) {
1019         case 32:
1020                 i = 0;
1021                 break;
1022         case 64:
1023                 i = 1;
1024                 break;
1025         default:
1026                 i = 2;
1027         }
1028
1029         if (tarval_cmp(tv, get_tarval_null(mode)) & pn_Cmp_Lt) {
1030                 tv = tarval_neg(tv);
1031                 res = -1;
1032         }
1033
1034         for (j = 0; j < fpa_max; ++j) {
1035                 if (tv == fpa_imm[i][j])
1036                         return res * j;
1037         }
1038         return fpa_max;
1039 }
1040
1041 /**
1042  * Transforms a Const node.
1043  *
1044  * @return The transformed ARM node.
1045  */
1046 static ir_node *gen_Const(ir_node *node) {
1047         ir_node  *block = be_transform_node(get_nodes_block(node));
1048         ir_mode *mode = get_irn_mode(node);
1049         dbg_info *dbg = get_irn_dbg_info(node);
1050
1051         if (mode_is_float(mode)) {
1052                 env_cg->have_fp_insn = 1;
1053                 if (USE_FPA(env_cg->isa)) {
1054                         tarval *tv = get_Const_tarval(node);
1055                         int imm = is_fpa_immediate(tv);
1056
1057                         if (imm != fpa_max) {
1058                                 if (imm > 0)
1059                                         node = new_bd_arm_fpaMvf_i(dbg, block, mode, imm);
1060                                 else
1061                                         node = new_bd_arm_fpaMnf_i(dbg, block, mode, -imm);
1062                         } else {
1063                                 node = new_bd_arm_fpaConst(dbg, block, tv);
1064                         }
1065                         be_dep_on_frame(node);
1066                         return node;
1067                 }
1068                 else if (USE_VFP(env_cg->isa)) {
1069                         assert(mode != mode_E && "IEEE Extended FP not supported");
1070                         panic("VFP not supported yet");
1071                 }
1072                 else {
1073                         panic("Softfloat not supported yet");
1074                 }
1075         }
1076         return create_const_graph(node, block);
1077 }
1078
1079 /**
1080  * Transforms a SymConst node.
1081  *
1082  * @return The transformed ARM node.
1083  */
1084 static ir_node *gen_SymConst(ir_node *node) {
1085         ir_node  *block = be_transform_node(get_nodes_block(node));
1086         ir_mode  *mode  = mode_Iu;
1087         dbg_info *dbg   = get_irn_dbg_info(node);
1088         ir_node  *res;
1089
1090         res = new_bd_arm_SymConst(dbg, block, mode, get_sc_ident(node));
1091         be_dep_on_frame(res);
1092         return res;
1093 }
1094
1095 /**
1096  * Transforms a CopyB node.
1097  *
1098  * @return The transformed ARM node.
1099  */
1100 static ir_node *gen_CopyB(ir_node *node) {
1101         ir_node  *block    = be_transform_node(get_nodes_block(node));
1102         ir_node  *src      = get_CopyB_src(node);
1103         ir_node  *new_src  = be_transform_node(src);
1104         ir_node  *dst      = get_CopyB_dst(node);
1105         ir_node  *new_dst  = be_transform_node(dst);
1106         ir_node  *mem      = get_CopyB_mem(node);
1107         ir_node  *new_mem  = be_transform_node(mem);
1108         ir_graph *irg      = current_ir_graph;
1109         dbg_info *dbg      = get_irn_dbg_info(node);
1110         int      size      = get_type_size_bytes(get_CopyB_type(node));
1111         ir_node  *src_copy;
1112         ir_node  *dst_copy;
1113
1114         src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], block, new_src);
1115         dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], block, new_dst);
1116
1117         return new_bd_arm_CopyB(dbg, block, dst_copy, src_copy,
1118                         new_bd_arm_EmptyReg(dbg, block, mode_Iu),
1119                         new_bd_arm_EmptyReg(dbg, block, mode_Iu),
1120                         new_bd_arm_EmptyReg(dbg, block, mode_Iu),
1121                         new_mem, size);
1122 }
1123
1124
1125 /********************************************
1126  *  _                          _
1127  * | |                        | |
1128  * | |__   ___ _ __   ___   __| | ___  ___
1129  * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
1130  * | |_) |  __/ | | | (_) | (_| |  __/\__ \
1131  * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
1132  *
1133  ********************************************/
1134
1135 /**
1136  * Return an expanding stack offset.
1137  * Note that function is called in the transform phase
1138  * where the stack offsets are still relative regarding
1139  * the first (frame allocating) IncSP.
1140  * However this is exactly what we want because frame
1141  * access must be done relative the the fist IncSP ...
1142  */
1143 static int get_sp_expand_offset(ir_node *inc_sp) {
1144         int offset = be_get_IncSP_offset(inc_sp);
1145
1146         if (offset == BE_STACK_FRAME_SIZE_EXPAND)
1147                 return 0;
1148
1149         return offset;
1150 }
1151
1152 #if 0
1153 static ir_node *gen_StackParam(ir_node *irn) {
1154         ir_node  *block    = be_transform_node(get_nodes_block(node));
1155         ir_node   *new_op = NULL;
1156         ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
1157         ir_node   *mem    = new_NoMem();
1158         ir_node   *ptr    = get_irn_n(irn, 0);
1159         ir_entity *ent    = be_get_frame_entity(irn);
1160         ir_mode   *mode   = env->mode;
1161
1162 //      /* If the StackParam has only one user ->     */
1163 //      /* put it in the Block where the user resides */
1164 //      if (get_irn_n_edges(node) == 1) {
1165 //              env->block = get_nodes_block(get_edge_src_irn(get_irn_out_edge_first(node)));
1166 //      }
1167
1168         if (mode_is_float(mode)) {
1169                 if (USE_SSE2(env->cg))
1170                         new_op = new_rd_ia32_fLoad(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1171                 else {
1172                         env->cg->used_x87 = 1;
1173                         new_op = new_rd_ia32_vfld(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1174                 }
1175         }
1176         else {
1177                 new_op = new_rd_ia32_Load(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
1178         }
1179
1180         set_ia32_frame_ent(new_op, ent);
1181         set_ia32_use_frame(new_op);
1182
1183         set_ia32_am_support(new_op, ia32_am_Source);
1184         set_ia32_op_type(new_op, ia32_AddrModeS);
1185         set_ia32_am_flavour(new_op, ia32_B);
1186         set_ia32_ls_mode(new_op, mode);
1187
1188         SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1189
1190         return new_rd_Proj(env->dbg, env->irg, block, new_op, mode, 0);
1191 }
1192 #endif
1193
1194 /**
1195  * Transforms a FrameAddr into an ARM Add.
1196  */
1197 static ir_node *gen_be_FrameAddr(ir_node *node) {
1198         ir_node   *block  = be_transform_node(get_nodes_block(node));
1199         ir_entity *ent    = be_get_frame_entity(node);
1200         int       offset  = get_entity_offset(ent);
1201         ir_node   *op     = be_get_FrameAddr_frame(node);
1202         ir_node   *new_op = be_transform_node(op);
1203         dbg_info  *dbg    = get_irn_dbg_info(node);
1204         ir_mode   *mode   = mode_Iu;
1205         ir_node   *cnst;
1206
1207         if (be_is_IncSP(op)) {
1208                 /* BEWARE: we get an offset which is absolute from an offset that
1209                    is relative. Both must be merged */
1210                 offset += get_sp_expand_offset(op);
1211         }
1212         cnst = create_const_graph_value(dbg, block, (unsigned)offset);
1213         if (is_arm_Mov_i(cnst))
1214                 return new_bd_arm_Add_i(dbg, block, new_op, mode, get_arm_imm_value(cnst));
1215         return new_bd_arm_Add(dbg, block, new_op, cnst, mode, ARM_SHF_NONE, 0);
1216 }
1217
1218 /**
1219  * Transform a be_AddSP into an arm_AddSP. Eat up const sizes.
1220  */
1221 static ir_node *gen_be_AddSP(ir_node *node) {
1222         ir_node  *block  = be_transform_node(get_nodes_block(node));
1223         ir_node  *sz     = get_irn_n(node, be_pos_AddSP_size);
1224         ir_node  *new_sz = be_transform_node(sz);
1225         ir_node  *sp     = get_irn_n(node, be_pos_AddSP_old_sp);
1226         ir_node  *new_sp = be_transform_node(sp);
1227         dbg_info *dbgi   = get_irn_dbg_info(node);
1228         ir_node  *nomem  = new_NoMem();
1229         ir_node  *new_op;
1230
1231         /* ARM stack grows in reverse direction, make a SubSPandCopy */
1232         new_op = new_bd_arm_SubSPandCopy(dbgi, block, new_sp, new_sz, nomem);
1233
1234         return new_op;
1235 }
1236
1237 /**
1238  * Transform a be_SubSP into an arm_SubSP. Eat up const sizes.
1239  */
1240 static ir_node *gen_be_SubSP(ir_node *node) {
1241         ir_node  *block  = be_transform_node(get_nodes_block(node));
1242         ir_node  *sz     = get_irn_n(node, be_pos_SubSP_size);
1243         ir_node  *new_sz = be_transform_node(sz);
1244         ir_node  *sp     = get_irn_n(node, be_pos_SubSP_old_sp);
1245         ir_node  *new_sp = be_transform_node(sp);
1246         dbg_info *dbgi   = get_irn_dbg_info(node);
1247         ir_node  *nomem  = new_NoMem();
1248         ir_node  *new_op;
1249
1250         /* ARM stack grows in reverse direction, make an AddSP */
1251         new_op = new_bd_arm_AddSP(dbgi, block, new_sp, new_sz, nomem);
1252
1253         return new_op;
1254 }
1255
1256 /**
1257  * Transform a be_Copy.
1258  */
1259 static ir_node *gen_be_Copy(ir_node *node) {
1260         ir_node *result = be_duplicate_node(node);
1261         ir_mode *mode   = get_irn_mode(result);
1262
1263         if (mode_needs_gp_reg(mode)) {
1264                 set_irn_mode(node, mode_Iu);
1265         }
1266
1267         return result;
1268 }
1269
1270 /**
1271  * Transform a Proj from a Load.
1272  */
1273 static ir_node *gen_Proj_Load(ir_node *node) {
1274         ir_node  *block    = be_transform_node(get_nodes_block(node));
1275         ir_node  *load     = get_Proj_pred(node);
1276         ir_node  *new_load = be_transform_node(load);
1277         dbg_info *dbgi     = get_irn_dbg_info(node);
1278         long     proj      = get_Proj_proj(node);
1279
1280         /* renumber the proj */
1281         switch (get_arm_irn_opcode(new_load)) {
1282         case iro_arm_Load:
1283         case iro_arm_Loadb:
1284         case iro_arm_Loadbs:
1285         case iro_arm_Loadh:
1286         case iro_arm_Loadhs:
1287                 /* handle all gp loads equal: they have the same proj numbers. */
1288                 if (proj == pn_Load_res) {
1289                         return new_rd_Proj(dbgi, block, new_load, mode_Iu, pn_arm_Load_res);
1290                 } else if (proj == pn_Load_M) {
1291                         return new_rd_Proj(dbgi, block, new_load, mode_M, pn_arm_Load_M);
1292                 }
1293                 break;
1294         case iro_arm_fpaLdf:
1295                 if (proj == pn_Load_res) {
1296                         ir_mode *mode = get_Load_mode(load);
1297                         return new_rd_Proj(dbgi, block, new_load, mode, pn_arm_fpaLdf_res);
1298                 } else if (proj == pn_Load_M) {
1299                         return new_rd_Proj(dbgi, block, new_load, mode_M, pn_arm_fpaLdf_M);
1300                 }
1301                 break;
1302         default:
1303                 break;
1304         }
1305         panic("Unsupported Proj from Load");
1306 }
1307
1308 /**
1309  * Transform and renumber the Projs from a CopyB.
1310  */
1311 static ir_node *gen_Proj_CopyB(ir_node *node) {
1312         ir_node  *block    = be_transform_node(get_nodes_block(node));
1313         ir_node  *pred     = get_Proj_pred(node);
1314         ir_node  *new_pred = be_transform_node(pred);
1315         dbg_info *dbgi     = get_irn_dbg_info(node);
1316         long     proj      = get_Proj_proj(node);
1317
1318         switch(proj) {
1319         case pn_CopyB_M_regular:
1320                 if (is_arm_CopyB(new_pred)) {
1321                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_CopyB_M);
1322                 }
1323                 break;
1324         default:
1325                 break;
1326         }
1327         panic("Unsupported Proj from CopyB");
1328 }
1329
1330 /**
1331  * Transform and renumber the Projs from a Quot.
1332  */
1333 static ir_node *gen_Proj_Quot(ir_node *node) {
1334         ir_node  *block    = be_transform_node(get_nodes_block(node));
1335         ir_node  *pred     = get_Proj_pred(node);
1336         ir_node  *new_pred = be_transform_node(pred);
1337         dbg_info *dbgi     = get_irn_dbg_info(node);
1338         ir_mode  *mode     = get_irn_mode(node);
1339         long     proj      = get_Proj_proj(node);
1340
1341         switch (proj) {
1342         case pn_Quot_M:
1343                 if (is_arm_fpaDvf(new_pred) || is_arm_fpaDvf_i(new_pred)) {
1344                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaDvf_M);
1345                 } else if (is_arm_fpaRdf(new_pred) || is_arm_fpaRdf_i(new_pred)) {
1346                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaRdf_M);
1347                 } else if (is_arm_fpaFdv(new_pred) || is_arm_fpaFdv_i(new_pred)) {
1348                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaFdv_M);
1349                 } else if (is_arm_fpaFrd(new_pred) || is_arm_fpaFrd_i(new_pred)) {
1350                         return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaFrd_M);
1351                 }
1352                 break;
1353         case pn_Quot_res:
1354                 if (is_arm_fpaDvf(new_pred) || is_arm_fpaDvf_i(new_pred)) {
1355                         return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaDvf_res);
1356                 } else if (is_arm_fpaRdf(new_pred) || is_arm_fpaRdf_i(new_pred)) {
1357                         return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaRdf_res);
1358                 } else if (is_arm_fpaFdv(new_pred) || is_arm_fpaFdv_i(new_pred)) {
1359                         return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaFdv_res);
1360                 } else if (is_arm_fpaFrd(new_pred) || is_arm_fpaFrd_i(new_pred)) {
1361                         return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaFrd_res);
1362                 }
1363                 break;
1364         default:
1365                 break;
1366         }
1367         panic("Unsupported Proj from Quot");
1368 }
1369
1370 /**
1371  * Transform the Projs of a be_AddSP.
1372  */
1373 static ir_node *gen_Proj_be_AddSP(ir_node *node) {
1374         ir_node  *block    = be_transform_node(get_nodes_block(node));
1375         ir_node  *pred     = get_Proj_pred(node);
1376         ir_node  *new_pred = be_transform_node(pred);
1377         dbg_info *dbgi     = get_irn_dbg_info(node);
1378         long     proj      = get_Proj_proj(node);
1379
1380         if (proj == pn_be_AddSP_sp) {
1381                 ir_node *res = new_rd_Proj(dbgi, block, new_pred, mode_Iu,
1382                                            pn_arm_SubSPandCopy_stack);
1383                 arch_set_irn_register(res, &arm_gp_regs[REG_SP]);
1384                 return res;
1385         } else if(proj == pn_be_AddSP_res) {
1386                 return new_rd_Proj(dbgi, block, new_pred, mode_Iu, pn_arm_SubSPandCopy_addr);
1387         } else if (proj == pn_be_AddSP_M) {
1388                 return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_SubSPandCopy_M);
1389         }
1390         panic("Unsupported Proj from AddSP");
1391 }
1392
1393 /**
1394  * Transform the Projs of a be_SubSP.
1395  */
1396 static ir_node *gen_Proj_be_SubSP(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_SubSP_sp) {
1404                 ir_node *res = new_rd_Proj(dbgi, block, new_pred, mode_Iu,
1405                                            pn_arm_AddSP_stack);
1406                 arch_set_irn_register(res, &arm_gp_regs[REG_SP]);
1407                 return res;
1408         } else if (proj == pn_be_SubSP_M) {
1409                 return new_rd_Proj(dbgi,  block, new_pred, mode_M, pn_arm_AddSP_M);
1410         }
1411         panic("Unsupported Proj from SubSP");
1412 }
1413
1414 /**
1415  * Transform the Projs from a Cmp.
1416  */
1417 static ir_node *gen_Proj_Cmp(ir_node *node) {
1418         (void) node;
1419         panic("Mux NYI");
1420 }
1421
1422
1423 /**
1424  * Transform the Thread Local Storage Proj.
1425  */
1426 static ir_node *gen_Proj_tls(ir_node *node) {
1427         ir_node  *block = be_transform_node(get_nodes_block(node));
1428         dbg_info *dbgi  = NULL;
1429
1430         return new_bd_arm_LdTls(dbgi, block, mode_Iu);
1431 }
1432
1433 /**
1434  * Transform a Proj node.
1435  */
1436 static ir_node *gen_Proj(ir_node *node) {
1437         ir_graph *irg  = current_ir_graph;
1438         dbg_info *dbgi = get_irn_dbg_info(node);
1439         ir_node  *pred = get_Proj_pred(node);
1440         long     proj  = get_Proj_proj(node);
1441
1442         if (is_Store(pred)) {
1443                 if (proj == pn_Store_M) {
1444                         return be_transform_node(pred);
1445                 } else {
1446                         panic("Unsupported Proj from Store");
1447                 }
1448         } else if (is_Load(pred)) {
1449                 return gen_Proj_Load(node);
1450         } else if (is_CopyB(pred)) {
1451                 return gen_Proj_CopyB(node);
1452         } else if (is_Quot(pred)) {
1453                 return gen_Proj_Quot(node);
1454         } else if (be_is_SubSP(pred)) {
1455                 return gen_Proj_be_SubSP(node);
1456         } else if (be_is_AddSP(pred)) {
1457                 return gen_Proj_be_AddSP(node);
1458         } else if (is_Cmp(pred)) {
1459                 return gen_Proj_Cmp(node);
1460         } else if (is_Start(pred)) {
1461                 if (proj == pn_Start_X_initial_exec) {
1462                         ir_node *block = get_nodes_block(pred);
1463                         ir_node *jump;
1464
1465                         /* we exchange the ProjX with a jump */
1466                         block = be_transform_node(block);
1467                         jump  = new_rd_Jmp(dbgi, block);
1468                         return jump;
1469                 }
1470                 if (node == get_irg_anchor(irg, anchor_tls)) {
1471                         return gen_Proj_tls(node);
1472                 }
1473         } else {
1474                 ir_node *new_pred = be_transform_node(pred);
1475                 ir_mode *mode     = get_irn_mode(node);
1476                 if (mode_needs_gp_reg(mode)) {
1477                         ir_node *block    = be_transform_node(get_nodes_block(node));
1478                         ir_node *new_proj = new_r_Proj(block, new_pred, mode_Iu,
1479                                                        get_Proj_proj(node));
1480                         new_proj->node_nr = node->node_nr;
1481                         return new_proj;
1482                 }
1483         }
1484
1485         return be_duplicate_node(node);
1486 }
1487
1488 typedef ir_node *(*create_const_node_func)(dbg_info *db, ir_node *block);
1489
1490 static inline ir_node *create_const(ir_node **place,
1491                                     create_const_node_func func,
1492                                     const arch_register_t* reg)
1493 {
1494         ir_node *block, *res;
1495
1496         if (*place != NULL)
1497                 return *place;
1498
1499         block = get_irg_start_block(env_cg->irg);
1500         res = func(NULL, block);
1501         arch_set_irn_register(res, reg);
1502         *place = res;
1503         return res;
1504 }
1505
1506 static ir_node *arm_new_Unknown_gp(void) {
1507         return create_const(&env_cg->unknown_gp, new_bd_arm_Unknown_GP,
1508                             &arm_gp_regs[REG_GP_UKNWN]);
1509 }
1510
1511 static ir_node *arm_new_Unknown_fpa(void) {
1512         return create_const(&env_cg->unknown_fpa, new_bd_arm_Unknown_FPA,
1513                             &arm_fpa_regs[REG_FPA_UKNWN]);
1514 }
1515
1516 /**
1517  * This function just sets the register for the Unknown node
1518  * as this is not done during register allocation because Unknown
1519  * is an "ignore" node.
1520  */
1521 static ir_node *gen_Unknown(ir_node *node) {
1522         ir_mode *mode = get_irn_mode(node);
1523         if (mode_is_float(mode)) {
1524                 if (USE_FPA(env_cg->isa))
1525                         return arm_new_Unknown_fpa();
1526                 else if (USE_VFP(env_cg->isa))
1527                         panic("VFP not supported yet");
1528                 else
1529                         panic("Softfloat not supported yet");
1530         } else if (mode_needs_gp_reg(mode)) {
1531                 return arm_new_Unknown_gp();
1532         } else {
1533                 assert(0 && "unsupported Unknown-Mode");
1534         }
1535
1536         return NULL;
1537 }
1538
1539 /**
1540  * Change some phi modes
1541  */
1542 static ir_node *gen_Phi(ir_node *node) {
1543         ir_node  *block = be_transform_node(get_nodes_block(node));
1544         ir_graph *irg   = current_ir_graph;
1545         dbg_info *dbgi  = get_irn_dbg_info(node);
1546         ir_mode  *mode  = get_irn_mode(node);
1547         ir_node  *phi;
1548
1549         if (mode_needs_gp_reg(mode)) {
1550                 /* we shouldn't have any 64bit stuff around anymore */
1551                 assert(get_mode_size_bits(mode) <= 32);
1552                 /* all integer operations are on 32bit registers now */
1553                 mode = mode_Iu;
1554         }
1555
1556         /* phi nodes allow loops, so we use the old arguments for now
1557          * and fix this later */
1558         phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node), get_irn_in(node) + 1);
1559         copy_node_attr(node, phi);
1560         be_duplicate_deps(node, phi);
1561
1562         be_enqueue_preds(node);
1563
1564         return phi;
1565 }
1566
1567 /*********************************************************
1568  *                  _             _      _
1569  *                 (_)           | |    (_)
1570  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
1571  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
1572  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
1573  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
1574  *
1575  *********************************************************/
1576
1577 /**
1578  * the BAD transformer.
1579  */
1580 static ir_node *bad_transform(ir_node *irn) {
1581         panic("ARM backend: Not implemented: %+F", irn);
1582         return irn;
1583 }
1584
1585 /**
1586  * Set a node emitter. Make it a bit more type safe.
1587  */
1588 static inline void set_transformer(ir_op *op, be_transform_func arm_transform_func) {
1589         op->ops.generic = (op_func)arm_transform_func;
1590 }
1591
1592 /**
1593  * Enters all transform functions into the generic pointer
1594  */
1595 static void arm_register_transformers(void) {
1596         /* first clear the generic function pointer for all ops */
1597         clear_irp_opcodes_generic_func();
1598
1599 #define GEN(a)     set_transformer(op_##a, gen_##a)
1600 #define BAD(a)     set_transformer(op_##a, bad_transform)
1601
1602         GEN(Add);
1603         GEN(Sub);
1604         GEN(Mul);
1605         BAD(Mulh);      /* unsupported yet */
1606         GEN(And);
1607         GEN(Or);
1608         GEN(Eor);
1609
1610         GEN(Shl);
1611         GEN(Shr);
1612         GEN(Shrs);
1613         GEN(Rotl);
1614
1615         GEN(Quot);
1616
1617         /* should be lowered */
1618         BAD(Div);
1619         BAD(Mod);
1620         BAD(DivMod);
1621
1622         GEN(Minus);
1623         GEN(Conv);
1624         GEN(Abs);
1625         GEN(Not);
1626
1627         GEN(Load);
1628         GEN(Store);
1629         GEN(Cond);
1630
1631         BAD(ASM);       /* unsupported yet */
1632         GEN(CopyB);
1633         BAD(Mux);       /* unsupported yet */
1634         GEN(Proj);
1635         GEN(Phi);
1636
1637         GEN(Const);
1638         GEN(SymConst);
1639
1640         /* we should never see these nodes */
1641         BAD(Raise);
1642         BAD(Sel);
1643         BAD(InstOf);
1644         BAD(Cast);
1645         BAD(Free);
1646         BAD(Tuple);
1647         BAD(Id);
1648         //BAD(Bad);
1649         BAD(Confirm);
1650         BAD(Filter);
1651         BAD(CallBegin);
1652         BAD(EndReg);
1653         BAD(EndExcept);
1654
1655         /* handle builtins */
1656         BAD(Builtin);
1657
1658         /* handle generic backend nodes */
1659         GEN(be_FrameAddr);
1660         //GEN(be_Call);
1661         //GEN(be_Return);
1662         GEN(be_AddSP);
1663         GEN(be_SubSP);
1664         GEN(be_Copy);
1665
1666         /* set the register for all Unknown nodes */
1667         GEN(Unknown);
1668
1669 #undef GEN
1670 #undef BAD
1671 }
1672
1673 /**
1674  * Pre-transform all unknown nodes.
1675  */
1676 static void arm_pretransform_node(void)
1677 {
1678         arm_code_gen_t *cg = env_cg;
1679
1680         cg->unknown_gp  = be_pre_transform_node(cg->unknown_gp);
1681         cg->unknown_fpa = be_pre_transform_node(cg->unknown_fpa);
1682 }
1683
1684 /**
1685  * Initialize fpa Immediate support.
1686  */
1687 static void arm_init_fpa_immediate(void) {
1688         /* 0, 1, 2, 3, 4, 5, 10, or 0.5. */
1689         fpa_imm[0][fpa_null]  = get_tarval_null(mode_F);
1690         fpa_imm[0][fpa_one]   = get_tarval_one(mode_F);
1691         fpa_imm[0][fpa_two]   = new_tarval_from_str("2", 1, mode_F);
1692         fpa_imm[0][fpa_three] = new_tarval_from_str("3", 1, mode_F);
1693         fpa_imm[0][fpa_four]  = new_tarval_from_str("4", 1, mode_F);
1694         fpa_imm[0][fpa_five]  = new_tarval_from_str("5", 1, mode_F);
1695         fpa_imm[0][fpa_ten]   = new_tarval_from_str("10", 2, mode_F);
1696         fpa_imm[0][fpa_half]  = new_tarval_from_str("0.5", 3, mode_F);
1697
1698         fpa_imm[1][fpa_null]  = get_tarval_null(mode_D);
1699         fpa_imm[1][fpa_one]   = get_tarval_one(mode_D);
1700         fpa_imm[1][fpa_two]   = new_tarval_from_str("2", 1, mode_D);
1701         fpa_imm[1][fpa_three] = new_tarval_from_str("3", 1, mode_D);
1702         fpa_imm[1][fpa_four]  = new_tarval_from_str("4", 1, mode_D);
1703         fpa_imm[1][fpa_five]  = new_tarval_from_str("5", 1, mode_D);
1704         fpa_imm[1][fpa_ten]   = new_tarval_from_str("10", 2, mode_D);
1705         fpa_imm[1][fpa_half]  = new_tarval_from_str("0.5", 3, mode_D);
1706
1707         fpa_imm[2][fpa_null]  = get_tarval_null(mode_E);
1708         fpa_imm[2][fpa_one]   = get_tarval_one(mode_E);
1709         fpa_imm[2][fpa_two]   = new_tarval_from_str("2", 1, mode_E);
1710         fpa_imm[2][fpa_three] = new_tarval_from_str("3", 1, mode_E);
1711         fpa_imm[2][fpa_four]  = new_tarval_from_str("4", 1, mode_E);
1712         fpa_imm[2][fpa_five]  = new_tarval_from_str("5", 1, mode_E);
1713         fpa_imm[2][fpa_ten]   = new_tarval_from_str("10", 2, mode_E);
1714         fpa_imm[2][fpa_half]  = new_tarval_from_str("0.5", 3, mode_E);
1715 }
1716
1717 /**
1718  * Transform a Firm graph into an ARM graph.
1719  */
1720 void arm_transform_graph(arm_code_gen_t *cg) {
1721         static int imm_initialized = 0;
1722
1723         if (! imm_initialized) {
1724                 arm_init_fpa_immediate();
1725                 imm_initialized = 1;
1726         }
1727         arm_register_transformers();
1728         env_cg = cg;
1729         be_transform_graph(cg->birg, arm_pretransform_node);
1730 }
1731
1732 void arm_init_transform(void) {
1733         // FIRM_DBG_REGISTER(dbg, "firm.be.arm.transform");
1734 }