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