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