added silence emitter for Projs and Phis
[libfirm] / ir / be / arm / arm_transform.c
1 /* The codegenrator (transform FIRM into arm FIRM */
2 /* $Id$ */
3
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
7
8 #include "irnode_t.h"
9 #include "irgraph_t.h"
10 #include "irmode_t.h"
11 #include "irgmod.h"
12 #include "iredges.h"
13 #include "irvrfy.h"
14 #include "ircons.h"
15 #include "dbginfo.h"
16 #include "iropt_t.h"
17 #include "debug.h"
18
19 #include "../benode_t.h"
20 #include "bearch_arm_t.h"
21
22 #include "arm_nodes_attr.h"
23 #include "../arch/archop.h"     /* we need this for Min and Max nodes */
24 #include "arm_transform.h"
25 #include "arm_new_nodes.h"
26 #include "arm_map_regs.h"
27
28 #include "gen_arm_regalloc_if.h"
29
30 #include <limits.h>
31
32 extern ir_op *get_op_Mulh(void);
33
34
35
36 /****************************************************************************************************
37  *                  _        _                        __                           _   _
38  *                 | |      | |                      / _|                         | | (_)
39  *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
40  * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
41  * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
42  * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
43  *
44  ****************************************************************************************************/
45
46 typedef struct vals_ {
47      int ops;
48      unsigned char values[4];
49      unsigned char shifts[4];
50 } vals;
51
52 static vals construct_vals(void) {
53         vals result = { 0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } };
54     return result;
55 }
56
57 static vals gen_vals_from_word(unsigned int value)
58 {
59      vals result = construct_vals();
60      int cur_offset = 0;
61      while (value != 0) {
62           if ((value & 3) == 0) {
63                cur_offset += 2;
64                value >>= 2;
65           } else {
66                result.values[result.ops] = value & 0xff;
67                result.shifts[result.ops] = cur_offset;
68                ++result.ops;
69                value >>= 8;
70                cur_offset += 8;
71           }
72      }
73      return result;
74 }
75
76 static ir_node *create_const_node(arm_transform_env_t *env, int value) {
77         ir_node *result = new_rd_arm_Const(env->dbg, env->irg, env->block, env->mode);
78         get_arm_attr(result)->value = new_tarval_from_long(value, env->mode);
79         return result;
80 }
81
82 #define NEW_BINOP_NODE(opname, env, op1, op2) new_rd_arm_##opname(env->dbg, env->irg, env->block, op1, op2, env->mode)
83
84 unsigned int create_shifter_operand(unsigned int shift, unsigned int immediate) {
85         return immediate | ((shift>>1)<<8);
86 }
87
88 static ir_node *create_const_graph_value(arm_transform_env_t *env, unsigned int value) {
89         ir_node *result;
90         int negate = 0;
91
92         if (value < 0x100 || ~value < 0x100 ) {
93                 if ( ~value < 0x100 ) {
94                         negate = 1;
95                         value = ~value;
96                 }
97                 result = create_const_node(env, value);
98         } else {
99                 vals v;
100                 vals v1 = gen_vals_from_word(value);
101                 vals v2 = gen_vals_from_word(~value);
102                 int cnt = 0;
103                 if (v2.ops == 1) {
104                         result = new_rd_arm_Const_Neg(env->dbg, env->irg, env->block, env->mode);
105                         set_arm_value(result, new_tarval_from_long(create_shifter_operand(v2.shifts[0], v2.values[0]), mode_Iu));
106                 } else {
107                         if ( v2.ops < v1.ops ) {
108                                 negate = 1;
109                                 v = v2;
110                         } else {
111                                 v = v1;
112                         }
113                         if (v.shifts[cnt] == 0) {
114                                 result = create_const_node(env, v.values[cnt]);
115                         } else {
116                                 result = create_const_node(env, create_shifter_operand(v.shifts[cnt], v.values[cnt]));
117                         }
118                         ++cnt;
119                         while(cnt < v.ops) {
120                                 ir_node *const_node = create_const_node(env, v.values[cnt]);
121                                 ir_node *orr_i_node = new_rd_arm_Or_i(env->dbg, env->irg, env->block, result, env->mode);
122                                 set_arm_value(orr_i_node, new_tarval_from_long(create_shifter_operand(v.shifts[cnt], v.values[cnt]), mode_Iu));
123                                 result = orr_i_node;
124                                 ++cnt;
125                         }
126                 }
127         }
128         if ( negate ) {
129                 result = new_rd_arm_Not(env->dbg, env->irg, env->block, result, env->mode);
130         }
131         return result;
132 }
133
134 // static ir_node *create_const_graph_value(arm_transform_env_t *env, unsigned int value) {
135 //      ir_node *irn = env->irn;
136 //      ir_node *result;
137 //      int negate = 0;
138 //
139 //      if ( ~value < 0x100 ) {
140 //              negate = 1;
141 //              value = ~value;
142 //      }
143 //
144 //      if (value < 0x100) {
145 //              return create_const_node(env, value);
146 //      } else {
147 //              vals v = gen_vals_from_word(value);
148 //              int cnt = 0;
149 //              ir_node *mov_val = create_const_node(env, v.values[cnt]);
150 //              if (v.shifts[cnt] != 0) {
151 //                      ir_node *shift_node = new_rd_arm_Shl_i(env->dbg, env->irg, env->block, mov_val, env->mode);
152 //                      set_arm_value(shift_node, new_tarval_from_long(v.shifts[cnt], mode_Iu));
153 //                      result = shift_node;
154 //              } else {
155 //                      result = mov_val;
156 //              }
157 //              ++cnt;
158 //              while(cnt < v.ops) {
159 //                      ir_node *const_node = create_const_node(env, v.values[cnt]);
160 //                      ir_node *orr_i_node = new_rd_arm_Or_i(env->dbg, env->irg, env->block, result, env->mode);
161 //                      unsigned shift = v.shifts[cnt];
162 //                      unsigned immediate = v.values[cnt];
163 //                      unsigned immediate_with_shift = immediate | ((shift>>1)<<8);
164 //                      set_arm_value(orr_i_node, new_tarval_from_long(immediate_with_shift, mode_Iu));
165 //                      result = orr_i_node;
166 //                      ++cnt;
167 //              }
168 //              return result;
169 //      }
170 // }
171
172 static ir_node *create_const_graph(arm_transform_env_t *env) {
173         int value = get_tarval_long(get_Const_tarval(env->irn));
174         return create_const_graph_value(env, value);
175 }
176
177
178
179 static ir_node *gen_Const(arm_transform_env_t *env) {
180         ir_node *result;
181         assert(env->mode != mode_E && "IEEE Extended FP not supported");
182         if (env->mode == mode_F) {
183                 result = new_rd_arm_fConst(env->dbg, env->irg, env->block, env->mode);
184                 get_arm_attr(result)->value = get_Const_tarval(env->irn);
185         } else if (env->mode == mode_D) {
186                 result = new_rd_arm_fConst(env->dbg, env->irg, env->block, env->mode);
187                 get_arm_attr(result)->value = get_Const_tarval(env->irn);
188         } else if (env->mode == mode_P) {
189                 return env->irn;
190         } else {
191                 result = create_const_graph(env);
192         }
193         return result;
194 }
195
196 static ir_node *gen_mask(arm_transform_env_t *env, ir_node *op, int result_bits) {
197         unsigned mask_bits = (1 << result_bits) - 1;
198         ir_node *mask_node = create_const_graph_value(env, mask_bits);
199         return new_rd_arm_And(env->dbg, env->irg, env->block, op, mask_node, get_irn_mode(env->irn));
200 }
201
202 static ir_node *gen_sign_extension(arm_transform_env_t *env, ir_node *op, int result_bits) {
203         int shift_width = 32 - result_bits;
204         ir_node *shift_const_node = create_const_graph_value(env, shift_width);
205         ir_node *lshift_node = new_rd_arm_Shl(env->dbg, env->irg, env->block, op, shift_const_node, get_irn_mode(op));
206         ir_node *rshift_node = new_rd_arm_Shrs(env->dbg, env->irg, env->block, lshift_node, shift_const_node, get_irn_mode(env->irn));
207         return rshift_node;
208 }
209
210 static ir_node *gen_Conv(arm_transform_env_t *env, ir_node *op) {
211         ir_mode *in_mode = get_irn_mode(op);
212         ir_mode *out_mode = env->mode;
213
214         assert( in_mode != mode_E && "");
215         assert( in_mode != mode_Ls && "");
216         assert( in_mode != mode_Lu && "");
217         assert( out_mode != mode_E && "");
218         assert( out_mode != mode_Ls && "");
219         assert( out_mode != mode_Lu && "");
220
221         if (in_mode == out_mode)
222                 return op;
223
224         if ((mode_is_int(in_mode) || mode_is_reference(in_mode))
225                 && (mode_is_reference(out_mode) || mode_is_int(out_mode))) {
226                 int in_bits = get_mode_size_bits(in_mode);
227                 int out_bits = get_mode_size_bits(out_mode);
228                 int in_sign = get_mode_sign(in_mode);
229                 int out_sign = get_mode_sign(out_mode);
230
231                 // 32 -> 32
232                         // NOPpen
233                 if (in_bits == out_bits && in_bits == 32)
234                         return op;
235
236                 // 16 -> 16
237                         // unsigned -> unsigned
238                                 // NOP
239                         // unsigned -> signed
240                                 // sign extension (31:16)=(15)
241                         // signed -> unsigned
242                                 // maskieren (31:16)=0
243                         // signed -> signed
244                                 // NOP
245                 if (in_bits == out_bits && out_bits < 32) {
246                         if (in_sign && !out_sign) {
247                                 return gen_mask(env, op, out_bits);
248                         } else {
249                                 return gen_sign_extension(env, op, out_bits);
250                         }
251                 }
252
253                 // 16 -> 32
254                         // unsigned -> unsigned
255                                 // NOP
256                         // unsigned -> signed
257                                 // NOP
258                         // signed -> unsigned
259                                 // sign extension (31:16)=(15)
260                         // signed -> signed
261                                 // sign extension (31:16)=(15)
262                 if (in_bits < out_bits) {
263                         if (in_sign) {
264                                 return gen_sign_extension(env, op, out_bits);
265                         } else {
266                                 return op;
267                         }
268                 }
269
270                 // 32 -> 16
271                         // unsigned -> unsigned
272                                 // maskieren (31:16)=0
273                         // unsigned -> signed
274                                 // maskieren (31:16)=0
275                         // signed -> unsigned
276                                 // maskieren (31:16)=0
277                         // signed -> signed
278                                 // sign extension (erledigt auch maskieren) (31:16)=(15)
279                 if (in_bits > out_bits) {
280                         if (in_sign && out_sign) {
281                                 return gen_sign_extension(env, op, out_bits);
282                         } else {
283                                 return gen_mask(env, op, out_bits);
284                         }
285                 }
286                 assert(0 && "recheck integer conversion logic!");
287                 return env->irn;
288         } else if (in_mode == mode_D && out_mode == mode_F) {
289                 return new_rd_arm_fConvD2S(env->dbg, env->irg, env->block, op, env->mode);
290         } else if (in_mode == mode_F && out_mode == mode_D) {
291                 return new_rd_arm_fConvS2D(env->dbg, env->irg, env->block, op, env->mode);
292         } else if (mode_is_int(in_mode) && mode_is_float(out_mode)) {
293                 return env->irn; /* TODO: implement int->float conversion*/
294         } else if (mode_is_float(in_mode) && mode_is_int(out_mode)) {
295                 return env->irn; /* TODO: implement float->int conversion*/
296         } else {
297                 assert(0 && "not implemented conversion");
298                 return env->irn;
299         }
300 }
301
302
303 /**
304  * Creates an arm Add.
305  *
306  * @param env   The transformation environment
307  * @param op1   first operator
308  * @param op2   second operator
309  * @return the created arm Add node
310  */
311 static ir_node *gen_Add(arm_transform_env_t *env, ir_node *op1, ir_node *op2) {
312         ir_node *result = NULL;
313         assert(!mode_is_float(env->mode) || (get_irn_mode(op1)->sort == get_irn_mode(op2)->sort));
314         assert(env->mode != mode_E && "IEEE Extended FP not supported");
315
316         if (env->mode == mode_F) {
317                 result = new_rd_arm_fAdds(env->dbg, env->irg, env->block, op1, op2, env->mode);
318         } else if (env->mode == mode_D) {
319                 result = new_rd_arm_fAddd(env->dbg, env->irg, env->block, op1, op2, env->mode);
320         } else if (mode_is_numP(env->mode)) {
321                 if (is_arm_Const(op1)) {
322                         result = new_rd_arm_Add_i(env->dbg, env->irg, env->block, op2, env->mode);
323                         set_arm_value(result, get_arm_value(op1));
324                 } else if (is_arm_Const(op2)) {
325                         result = new_rd_arm_Add_i(env->dbg, env->irg, env->block, op1, env->mode);
326                         set_arm_value(result, get_arm_value(op2));
327                 } else {
328                         result = new_rd_arm_Add(env->dbg, env->irg, env->block, op1, op2, env->mode);
329                 }
330         } else {
331                 assert(0 && "unknown mode for add");
332         }
333         return result;
334 }
335
336
337
338 /**
339  * Creates an arm Mul.
340  *
341  * @param dbg       firm node dbg
342  * @param block     the block the new node should belong to
343  * @param op1       first operator
344  * @param op2       second operator
345  * @param mode      node mode
346  * @return the created arm Mul node
347  */
348 static ir_node *gen_Mul(arm_transform_env_t *env, ir_node *op1, ir_node *op2) {
349         assert(!mode_is_float(env->mode) || (get_irn_mode(op1)->sort == get_irn_mode(op2)->sort));
350         assert(env->mode != mode_E && "IEEE Extended FP not supported");
351
352         if (env->mode == mode_F) {
353                 return new_rd_arm_fMuls(env->dbg, env->irg, env->block, op1, op2, env->mode);
354         }
355         if (env->mode == mode_D) {
356                 return new_rd_arm_fMuld(env->dbg, env->irg, env->block, op1, op2, env->mode);
357         }
358         return new_rd_arm_Mul(env->dbg, env->irg, env->block, op1, op2, env->mode);
359 }
360
361
362 /**
363  * Creates an arm floating Div.
364  *
365  * @param dbg       firm node dbg
366  * @param block     the block the new node should belong to
367  * @param op1       first operator
368  * @param op2       second operator
369  * @param mode      node mode
370  * @return the created arm fDiv node
371  */
372 static ir_node *gen_Quot(arm_transform_env_t *env, ir_node *op1, ir_node *op2) {
373         // assert(mode_is_float(env->mode) && "only floating point supported");
374         assert(get_irn_mode(op1)->sort == get_irn_mode(op2)->sort);
375         assert(mode_is_float(get_irn_mode(op1)));
376         assert(get_irn_mode(op1) != mode_E && "IEEE Extended FP not supported");
377
378         if (get_irn_mode(op1) == mode_F) {
379                 return new_rd_arm_fDivs(env->dbg, env->irg, env->block, op1, op2, env->mode);
380         }
381         return new_rd_arm_fDivd(env->dbg, env->irg, env->block, op1, op2, env->mode);
382 }
383
384
385 /**
386  * Creates an arm And.
387  *
388  * @param dbg       firm node dbg
389  * @param block     the block the new node should belong to
390  * @param op1       first operator
391  * @param op2       second operator
392  * @param mode      node mode
393  * @return the created arm And node
394  */
395 static ir_node *gen_And(arm_transform_env_t *env, ir_node *op1, ir_node *op2) {
396         ir_node *result;
397         if (is_arm_Const(op1)) {
398                 result = new_rd_arm_And_i(env->dbg, env->irg, env->block, op2, env->mode);
399                 set_arm_value(result, get_arm_value(op1));
400         } else if (is_arm_Const(op2)) {
401                 result = new_rd_arm_And_i(env->dbg, env->irg, env->block, op1, env->mode);
402                 set_arm_value(result, get_arm_value(op2));
403         } else {
404                 result = new_rd_arm_And(env->dbg, env->irg, env->block, op1, op2, env->mode);
405         }
406         return result;
407 }
408
409
410
411 /**
412  * Creates an arm Or.
413  *
414  * @param dbg       firm node dbg
415  * @param block     the block the new node should belong to
416  * @param op1       first operator
417  * @param op2       second operator
418  * @param mode      node mode
419  * @return the created arm Or node
420  */
421 static ir_node *gen_Or(arm_transform_env_t *env, ir_node *op1, ir_node *op2) {
422         ir_node *result;
423         if (is_arm_Const(op1)) {
424                 result = new_rd_arm_Or_i(env->dbg, env->irg, env->block, op2, env->mode);
425                 set_arm_value(result, get_arm_value(op1));
426         } else if (is_arm_Const(op2)) {
427                 result = new_rd_arm_Or_i(env->dbg, env->irg, env->block, op1, env->mode);
428                 set_arm_value(result, get_arm_value(op2));
429         } else {
430                 result = new_rd_arm_Or(env->dbg, env->irg, env->block, op1, op2, env->mode);
431         }
432         return result;
433 }
434
435
436
437 /**
438  * Creates an arm Eor.
439  *
440  * @param dbg       firm node dbg
441  * @param block     the block the new node should belong to
442  * @param op1       first operator
443  * @param op2       second operator
444  * @param mode      node mode
445  * @return the created arm Eor node
446  */
447 static ir_node *gen_Eor(arm_transform_env_t *env, ir_node *op1, ir_node *op2) {
448         ir_node *result;
449         if (is_arm_Const(op1)) {
450                 result = new_rd_arm_Eor_i(env->dbg, env->irg, env->block, op2, env->mode);
451                 set_arm_value(result, get_arm_value(op1));
452         } else if (is_arm_Const(op2)) {
453                 result = new_rd_arm_Eor_i(env->dbg, env->irg, env->block, op1, env->mode);
454                 set_arm_value(result, get_arm_value(op2));
455         } else {
456                 result = new_rd_arm_Eor(env->dbg, env->irg, env->block, op1, op2, env->mode);
457         }
458         return result;
459 }
460
461
462
463 /**
464  * Creates an arm Sub.
465  *
466  * @param dbg       firm node dbg
467  * @param block     the block the new node should belong to
468  * @param op1       first operator
469  * @param op2       second operator
470  * @param mode      node mode
471  * @return the created arm Sub node
472  */
473 static ir_node *gen_Sub(arm_transform_env_t *env, ir_node *op1, ir_node *op2) {
474         ir_node *result = NULL;
475         assert(!mode_is_float(env->mode) || (get_irn_mode(op1)->sort == get_irn_mode(op2)->sort));
476         assert(env->mode != mode_E && "IEEE Extended FP not supported");
477
478         if (env->mode == mode_F) {
479                 result = new_rd_arm_fSubs(env->dbg, env->irg, env->block, op1, op2, env->mode);
480         } else if (env->mode == mode_D) {
481                 result = new_rd_arm_fSubd(env->dbg, env->irg, env->block, op1, op2, env->mode);
482         } else if (mode_is_numP(env->mode)) {
483                 if (is_arm_Const(op2)) {
484                         result = new_rd_arm_Sub_i(env->dbg, env->irg, env->block, op1, env->mode);
485                         set_arm_value(result, get_arm_value(op2));
486                 } else {
487                         result = new_rd_arm_Sub(env->dbg, env->irg, env->block, op1, op2, env->mode);
488                 }
489         } else {
490                 assert(0 && "unknown mode for sub");
491         }
492         return result;
493 }
494
495 /**
496  * Creates an arm Shl.
497  *
498  * @param dbg       firm node dbg
499  * @param block     the block the new node should belong to
500  * @param op1       first operator
501  * @param op2       second operator
502  * @param mode      node mode
503  * @return the created arm Shl node
504  */
505 static ir_node *gen_Shl(arm_transform_env_t *env, ir_node *op1, ir_node *op2) {
506         ir_node *result;
507         if (is_arm_Const(op2)) {
508                 result = new_rd_arm_Shl_i(env->dbg, env->irg, env->block, op1, env->mode);
509                 set_arm_value(result, get_arm_value(op2));
510         } else {
511                 result = new_rd_arm_Shl(env->dbg, env->irg, env->block, op1, op2, env->mode);
512         }
513         return result;
514 }
515
516
517
518 /**
519  * Creates an arm Shr.
520  *
521  * @param dbg       firm node dbg
522  * @param block     the block the new node should belong to
523  * @param op1       first operator
524  * @param op2       second operator
525  * @param mode      node mode
526  * @return the created arm Shr node
527  */
528 static ir_node *gen_Shr(arm_transform_env_t *env, ir_node *op1, ir_node *op2) {
529         ir_node *result;
530         if (is_arm_Const(op2)) {
531                 result = new_rd_arm_Shr_i(env->dbg, env->irg, env->block, op1, env->mode);
532                 set_arm_value(result, get_arm_value(op2));
533         } else {
534                 result = new_rd_arm_Shr(env->dbg, env->irg, env->block, op1, op2, env->mode);
535         }
536         return result;
537 }
538
539 /**
540  * Creates an arm Shrs.
541  *
542  * @param dbg       firm node dbg
543  * @param block     the block the new node should belong to
544  * @param op1       first operator
545  * @param op2       second operator
546  * @param mode      node mode
547  * @return the created arm Shrs node
548  */
549 static ir_node *gen_Shrs(arm_transform_env_t *env, ir_node *op1, ir_node *op2) {
550         ir_node *result;
551         if (is_arm_Const(op2)) {
552                 result = new_rd_arm_Shrs_i(env->dbg, env->irg, env->block, op1, env->mode);
553                 set_arm_value(result, get_arm_value(op2));
554         } else {
555                 result = new_rd_arm_Shrs(env->dbg, env->irg, env->block, op1, op2, env->mode);
556         }
557         return result;
558 }
559
560 /**
561  * Transforms a Not node.
562  *
563  * @param mod     the debug module
564  * @param block   the block the new node should belong to
565  * @param node    the ir Not node
566  * @param op      operator
567  * @param mode    node mode
568  * @return the created arm Not node
569  */
570 static ir_node *gen_Not(arm_transform_env_t *env, ir_node *op) {
571         return new_rd_arm_Not(env->dbg, env->irg, env->block, op, env->mode);
572 }
573
574
575 static ir_node *gen_Abs(arm_transform_env_t *env, ir_node *op) {
576         assert(env->mode != mode_E && "IEEE Extended FP not supported");
577
578         if (env->mode == mode_F) {
579                 return new_rd_arm_fAbss(env->dbg, env->irg, env->block, op, env->mode);
580         }
581         if (env->mode == mode_D) {
582                 return new_rd_arm_fAbsd(env->dbg, env->irg, env->block, op, env->mode);
583         }
584
585         return new_rd_arm_Abs(env->dbg, env->irg, env->block, op, env->mode);
586 }
587
588
589 /**
590  * Transforms a Minus node.
591  *
592  * @param mod     the debug module
593  * @param block   the block the new node should belong to
594  * @param node    the ir Minus node
595  * @param op      operator
596  * @param mode    node mode
597  * @return the created arm Minus node
598  */
599 static ir_node *gen_Minus(arm_transform_env_t *env, ir_node *op) {
600         if (mode_is_float(env->mode)) {
601                 return new_rd_arm_fMinus(env->dbg, env->irg, env->block, op, env->mode);
602         }
603         return new_rd_arm_Minus(env->dbg, env->irg, env->block, op, env->mode);
604 }
605
606
607 /**
608  * Transforms a Load.
609  *
610  * @param mod     the debug module
611  * @param block   the block the new node should belong to
612  * @param node    the ir Load node
613  * @param mode    node mode
614  * @return the created arm Load node
615  */
616 static ir_node *gen_Load(arm_transform_env_t *env) {
617         ir_node *node = env->irn;
618         ir_mode *mode = get_Load_mode(node);
619
620 //      const ir_edge_t *edge;
621 //
622 //      foreach_out_edge(node, edge) {
623 //              ir_node* proj = get_edge_src_irn(edge);
624 //              long nr = get_Proj_proj(proj);
625 //              if ( nr == pn_Load_res )
626 //                      mode = proj->mode;
627 //      }
628 //     besser: get_Load_mode() verwenden!
629
630         assert(mode!=NULL && "irgendwie hat das load kein proj fuers result");
631         if (mode==mode_F) {
632                 return new_rd_arm_fLoads(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
633         }
634         if (mode==mode_D) {
635                 return new_rd_arm_fLoadd(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
636         }
637         if (mode == mode_Bu) {
638                 return new_rd_arm_Loadb(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
639         }
640         if (mode == mode_Bs) {
641                 return new_rd_arm_Loadbs(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
642         }
643         if (mode == mode_Hu) {
644                 return new_rd_arm_Loadh(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
645         }
646         if (mode == mode_Hs) {
647                 return new_rd_arm_Loadhs(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
648         }
649         if (mode_is_reference(mode)) {
650                 return new_rd_arm_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
651         }
652         return new_rd_arm_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
653 }
654
655
656
657 /**
658  * Transforms a Store.
659  *
660  * @param mod     the debug module
661  * @param block   the block the new node should belong to
662  * @param node    the ir Store node
663  * @param mode    node mode
664  * @return the created arm Store node
665  */
666 static ir_node *gen_Store(arm_transform_env_t *env) {
667         ir_node *node = env->irn;
668         ir_mode *mode = get_irn_mode(get_Store_value(node));
669         assert(env->mode != mode_E && "IEEE Extended FP not supported");
670
671         if (mode == mode_F) {
672                 return new_rd_arm_fStores(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
673         }
674         if (mode == mode_D) {
675                 return new_rd_arm_fStored(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
676         }
677         if (mode == mode_Bu) {
678                 return new_rd_arm_Storeb(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
679         }
680         if (mode == mode_Bs) {
681                 return new_rd_arm_Storebs(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
682         }
683         if (mode == mode_Hu) {
684                 return new_rd_arm_Storeh(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
685         }
686         if (mode == mode_Hs) {
687                 return new_rd_arm_Storehs(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
688         }
689         return new_rd_arm_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
690 }
691
692
693 static ir_node *gen_Cond(arm_transform_env_t *env) {
694         ir_node *result   = NULL;
695         ir_node *selector = get_Cond_selector(env->irn);
696         ir_node *irn      = env->irn;
697
698         if ( get_irn_mode(selector) == mode_b ) {
699                 //CondJmp
700                 ir_node *proj_node = get_Cond_selector(irn);
701                 ir_node *cmp_node = get_Proj_pred(proj_node);
702                 ir_node *op1 = get_Cmp_left(cmp_node);
703                 ir_node *op2 = get_Cmp_right(cmp_node);
704                 result = new_rd_arm_CondJmp(env->dbg, env->irg, env->block, op1, op2, mode_T);
705                 set_arm_proj_num(result, get_Proj_proj(proj_node));
706         } else {
707                 //SwitchJmp
708                 ir_node *op = get_irn_n(env->irn, 0);
709                 ir_node *const_graph;
710                 ir_node *sub;
711                 ir_node *const_node;
712
713                 ir_node *proj;
714                 const ir_edge_t *edge;
715                 int min = INT_MAX;
716                 int max = INT_MIN;
717                 int translation;
718                 int norm_max;
719                 int norm_min;
720                 int pn;
721                 arm_transform_env_t const_env;
722                 int n_projs;
723                 ir_node **projs;
724
725                 foreach_out_edge(irn, edge) {
726                         proj = get_edge_src_irn(edge);
727                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
728
729                         pn = get_Proj_proj(proj);
730
731                         min = pn<min ? pn : min;
732                         max = pn>max ? pn : max;
733                 }
734                 translation = min;
735                 norm_max = max - translation;
736                 norm_min = min - translation;
737
738                 n_projs = norm_max + 1;
739                 projs = xcalloc(n_projs , sizeof(ir_node*));
740
741
742                 foreach_out_edge(irn, edge) {
743                         proj = get_edge_src_irn(edge);
744                         assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
745
746                         pn = get_Proj_proj(proj) - translation;
747                         set_Proj_proj(proj, pn);
748                 }
749
750
751                 const_node = new_rd_Const(env->dbg, env->irg, env->block, mode_Iu, new_tarval_from_long(translation, mode_Iu));
752                 const_env = *env;
753                 const_env.mode = mode_Is;
754                 const_env.irn = const_node;
755                 const_graph = gen_Const(&const_env);
756                 sub = new_rd_arm_Sub(env->dbg, env->irg, env->block, op, const_graph, get_irn_mode(op));
757                 result = new_rd_arm_SwitchJmp(env->dbg, env->irg, env->block, sub, mode_T);
758                 set_arm_n_projs(result, n_projs);
759                 set_arm_default_proj_num(result, get_Cond_defaultProj(irn)-translation);
760         }
761         return result;
762 }
763
764 /**
765  * Returns the name of a SymConst.
766  * @param symc  the SymConst
767  * @return name of the SymConst
768  */
769 const char *get_sc_name(ir_node *symc) {
770         if (get_irn_opcode(symc) != iro_SymConst)
771                 return "NONE";
772
773         switch (get_SymConst_kind(symc)) {
774                 case symconst_addr_name:
775                         return get_id_str(get_SymConst_name(symc));
776
777                 case symconst_addr_ent:
778                         return get_entity_ld_name(get_SymConst_entity(symc));
779
780                 default:
781                         assert(0 && "Unsupported SymConst");
782         }
783
784         return NULL;
785 }
786
787 static ir_node *gen_SymConst(arm_transform_env_t *env) {
788         ir_node *result;
789         const char *str = get_sc_name(env->irn);
790         result = new_rd_arm_SymConst(env->dbg, env->irg, env->block, env->mode);
791         set_arm_symconst_label(result, str);
792         return result;
793 }
794
795
796
797
798
799 /**
800  * Transforms a CopyB node.
801  *
802  * @param env   The transformation environment
803  * @return The transformed node.
804  */
805 static ir_node *gen_CopyB(arm_transform_env_t *env) {
806         ir_node  *res   = NULL;
807         dbg_info *dbg   = env->dbg;
808         ir_graph *irg   = env->irg;
809         ir_mode  *mode  = env->mode;
810         ir_node  *block = env->block;
811         ir_node  *node  = env->irn;
812         ir_node  *src   = get_CopyB_src(node);
813         ir_node  *dst   = get_CopyB_dst(node);
814         ir_node  *mem   = get_CopyB_mem(node);
815         int       size  = get_type_size_bytes(get_CopyB_type(node));
816         ir_node *src_copy;
817         ir_node *dst_copy;
818
819         arm_transform_env_t const_env;
820         const_env.block    = block;
821         const_env.dbg      = dbg;
822         const_env.irg      = irg;
823         const_env.irn      = node;
824         DEBUG_ONLY(const_env.mod      = env->mod;)
825         const_env.mode     = mode_Iu;
826
827         src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_general_purpose], irg, block, src);
828         dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_general_purpose], irg, block, dst);
829
830         res = new_rd_arm_CopyB( dbg, irg, block, dst_copy, src_copy, new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), mem, mode);
831         set_arm_value(res, new_tarval_from_long(size, mode_Iu));
832
833         return res;
834 }
835
836
837
838
839
840 // /************************************************************************/
841 // /* be transforms                                                        */
842 // /************************************************************************/
843 //
844 // static ir_node *gen_be_Copy(arm_transform_env_t *env, ir_node *op) {
845 //      return new_rd_arm_Copy(env->dbg, env->irg, env->block, op, env->mode);
846 // }
847
848 /*********************************************************
849  *                  _             _      _
850  *                 (_)           | |    (_)
851  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
852  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
853  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
854  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
855  *
856  *********************************************************/
857
858 /************************************************************************/
859 /* move constants out of startblock                                       */
860 /************************************************************************/
861 void arm_move_consts(ir_node *node, void *env) {
862         arm_code_gen_t *cgenv = (arm_code_gen_t *)env;
863         int i;
864         if (is_Block(node))
865                 return;
866         if (is_Phi(node)) {
867                 for (i=0; i<get_irn_arity(node); i++) {
868                         ir_node *pred = get_irn_n(node,i);
869                         opcode pred_code = get_irn_opcode(pred);
870                         if (pred_code == iro_Const) {
871                                 ir_node *const_graph;
872                                 arm_transform_env_t tenv;
873                                 tenv.block    = get_nodes_block(get_irn_n(get_nodes_block(node),i));
874                                 tenv.dbg      = get_irn_dbg_info(pred);
875                                 tenv.irg      = current_ir_graph;
876                                 tenv.irn      = pred;
877                                 DEBUG_ONLY(tenv.mod      = cgenv->mod;)
878                                 tenv.mode     = get_irn_mode(pred);
879                                 const_graph = create_const_graph(&tenv);
880                                 set_irn_n(node, i, const_graph);
881                         } else if (pred_code == iro_SymConst) {
882                                 const char *str = get_sc_name(pred);
883                                 ir_node *symconst_node;
884                                 symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
885                                         current_ir_graph, get_nodes_block(get_irn_n(get_nodes_block(node),i)), get_irn_mode(pred));
886                                 set_arm_symconst_label(symconst_node, str);
887                                 set_irn_n(node, i, symconst_node);
888                         }
889                 }
890                 return;
891         }
892         for (i=0; i<get_irn_arity(node); i++) {
893                 ir_node *pred = get_irn_n(node,i);
894                 opcode pred_code = get_irn_opcode(pred);
895                 if (pred_code == iro_Const) {
896                         ir_node *const_graph;
897                         arm_transform_env_t tenv;
898                         tenv.block    = get_nodes_block(node);
899                         tenv.dbg      = get_irn_dbg_info(pred);
900                         tenv.irg      = current_ir_graph;
901                         tenv.irn      = pred;
902                         DEBUG_ONLY(tenv.mod      = cgenv->mod;)
903                         tenv.mode     = get_irn_mode(pred);
904                         const_graph = create_const_graph(&tenv);
905                         set_irn_n(node, i, const_graph);
906                 } else if (pred_code == iro_SymConst) {
907                         const char *str = get_sc_name(pred);
908                         ir_node *symconst_node;
909                         symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
910                                 current_ir_graph, get_nodes_block(node), get_irn_mode(pred));
911                         set_arm_symconst_label(symconst_node, str);
912                         set_irn_n(node, i, symconst_node);
913                 }
914         }
915 }
916
917
918 /************************************************************************/
919 /* move symbolic constants out of startblock                            */
920 /************************************************************************/
921 void arm_move_symconsts(ir_node *node, void *env) {
922         int i;
923
924         if (is_Block(node))
925                 return;
926
927         for (i = 0; i  < get_irn_arity(node); i++) {
928                 ir_node *pred      = get_irn_n(node,i);
929                 opcode   pred_code = get_irn_opcode(pred);
930
931                 if (pred_code == iro_SymConst) {
932                         const char *str = get_sc_name(pred);
933                         ir_node    *symconst_node;
934
935                         symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
936                                 current_ir_graph, get_nodes_block(node), get_irn_mode(pred));
937
938                         set_arm_symconst_label(symconst_node, str);
939                         set_irn_n(node, i, symconst_node);
940                 }
941         }
942 }
943
944
945 /**
946  * Transforms the given firm node (and maybe some other related nodes)
947  * into one or more assembler nodes.
948  *
949  * @param node    the firm node
950  * @param env     the debug module
951  */
952 void arm_transform_node(ir_node *node, void *env) {
953         arm_code_gen_t *cgenv = (arm_code_gen_t *)env;
954         opcode  code               = get_irn_opcode(node);
955         ir_node *asm_node          = NULL;
956         arm_transform_env_t tenv;
957
958         if (is_Block(node))
959                 return;
960
961         tenv.block    = get_nodes_block(node);
962         tenv.dbg      = get_irn_dbg_info(node);
963         tenv.irg      = current_ir_graph;
964         tenv.irn      = node;
965         DEBUG_ONLY(tenv.mod      = cgenv->mod;)
966         tenv.mode     = get_irn_mode(node);
967
968 #define UNOP(a)        case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break
969 #define BINOP(a)       case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break
970 #define GEN(a)         case iro_##a: asm_node = gen_##a(&tenv); break
971 #define IGN(a)         case iro_##a: break
972 #define BAD(a)         case iro_##a: goto bad
973
974         DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
975
976         switch (code) {
977                 BINOP(Add);  // done
978                 BINOP(Mul);  // done
979                 BINOP(Quot); // done
980                 BINOP(And);  // done
981                 BINOP(Or);   // done
982                 BINOP(Eor);  // done
983
984                 BINOP(Sub);  // done
985                 BINOP(Shl);  // done
986                 BINOP(Shr);  // done
987                 BINOP(Shrs); // done
988
989                 UNOP(Minus); // done
990                 UNOP(Not);   // done
991                 UNOP(Abs);   // done
992
993                 GEN(CopyB); // done
994                 GEN(Const); // TODO: floating point consts
995                 UNOP(Conv); // TODO: floating point conversions
996
997                 GEN(Load);   // done
998                 GEN(Store);  // done
999
1000                 GEN(SymConst);
1001                 GEN(Cond);        // integer done
1002
1003                 /* TODO: implement these nodes */
1004
1005                 IGN(Div);    // intrinsic lowering
1006                 IGN(Mod);    // intrinsic lowering
1007                 IGN(DivMod); // TODO: implement DivMod
1008
1009                 IGN(Mux);
1010                 IGN(Unknown);
1011                 IGN(Cmp);     // done, implemented in cond
1012
1013                 /* You probably don't need to handle the following nodes */
1014
1015                 IGN(Call);
1016                 IGN(Proj);
1017                 IGN(Alloc);
1018
1019                 IGN(Block);
1020                 IGN(Start);
1021                 IGN(End);
1022                 IGN(NoMem);
1023                 IGN(Phi);
1024                 IGN(IJmp);
1025                 IGN(Jmp);     // emitter done
1026                 IGN(Break);
1027                 IGN(Sync);
1028
1029                 BAD(Raise);
1030                 BAD(Sel);
1031                 BAD(InstOf);
1032                 BAD(Cast);
1033                 BAD(Free);
1034                 BAD(Tuple);
1035                 BAD(Id);
1036                 BAD(Bad);
1037                 BAD(Confirm);
1038                 BAD(Filter);
1039                 BAD(CallBegin);
1040                 BAD(EndReg);
1041                 BAD(EndExcept);
1042
1043                 default:
1044                         if (get_irn_op(node) == get_op_Max() ||
1045                                 get_irn_op(node) == get_op_Min() ||
1046                                 get_irn_op(node) == get_op_Mulh())
1047                         {
1048                                 /* TODO: implement */
1049                                 /* ignore for now  */
1050                         }
1051                         break;
1052 bad:
1053                 fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
1054                 assert(0);
1055         }
1056
1057         if (asm_node) {
1058                 exchange(node, asm_node);
1059                 DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1060         }
1061         else {
1062                 DB((tenv.mod, LEVEL_1, "ignored\n"));
1063         }
1064 }