remove arch_irn_class_is macro as it hides usages of arch_irn_class_XXX from grep...
[libfirm] / ir / be / ppc32 / ppc32_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 ppc FIRM)
23  * @author  Moritz Kroll, Jens Mueller
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 "iredges_t.h"
34 #include "irvrfy.h"
35 #include "ircons.h"
36 #include "iropt_t.h"
37 #include "irprintf.h"
38 #include "debug.h"
39 #include "error.h"
40
41 #include "../benode.h"
42 #include "bearch_ppc32_t.h"
43
44 #include "ppc32_nodes_attr.h"
45 #include "ppc32_transform.h"
46 #include "ppc32_new_nodes.h"
47 #include "ppc32_map_regs.h"
48
49 #include "gen_ppc32_regalloc_if.h"
50
51 extern ir_op *get_op_Mulh(void);
52
53 ir_mode* ppc32_mode_Cond = NULL;
54
55 /**
56  * Returns the proj of a given node with the given proj number
57  */
58 static inline ir_node *get_succ_Proj(ir_node *node, long proj)
59 {
60         const ir_edge_t *edge;
61         foreach_out_edge(node, edge)
62         {
63                 if (is_Proj(edge->src) && get_Proj_proj(edge->src) == proj)
64                         return edge->src;
65         }
66         return NULL;
67 }
68
69 /**
70  * Returns a singleton condition mode
71  */
72 static ir_mode *get_ppc32_mode_Cond(void)
73 {
74         if (ppc32_mode_Cond)
75                 return ppc32_mode_Cond;
76         else {
77                 ppc32_mode_Cond = new_ir_mode("mode_Cond", irms_int_number, 4, 0, irma_none, 0);
78                 return ppc32_mode_Cond;
79         }
80 }
81
82 /**
83  * Calculates the ppc32_modecode with size, sort and signed attributes
84  */
85 ppc32_modecode get_nice_modecode(ir_mode *irmode)
86 {
87         ppc32_modecode mode = irm_max;
88         int sign = mode_is_signed(irmode);
89         int bits = get_mode_size_bits(irmode);
90         if (mode_is_int(irmode))
91         {
92                 switch (bits)
93                 {
94                         case 8:
95                                 mode = sign ? irm_Bs : irm_Bu;
96                                 break;
97                         case 16:
98                                 mode = sign ? irm_Hs : irm_Hu;
99                                 break;
100                         case 32:
101                                 mode = sign ? irm_Is : irm_Iu;
102                                 break;
103                 }
104         }
105         else if (mode_is_float(irmode))
106         {
107                 switch (bits)
108                 {
109                         case 32:
110                                 mode = irm_F;
111                                 break;
112                         case 64:
113                                 mode = irm_D;
114                                 break;
115                 }
116         }
117         else if (mode_is_reference(irmode))
118         {
119                 switch (bits)
120                 {
121                         case 32:
122                                 mode = irm_P;
123                                 break;
124                 }
125         }
126         return mode;
127 }
128
129 /**
130  * Returns true, if the given node is a Const node and it's value fits into
131  * a signed 16-bit variable
132  */
133 static int is_16bit_signed_const(ir_node *node)
134 {
135         tarval *tv_const;
136
137         if (!is_ppc32_Const(node)) return 0;
138
139         tv_const = get_ppc32_constant_tarval(node);
140
141         switch (get_nice_modecode(get_irn_mode(node)))
142         {
143                 case irm_Bu:
144                 case irm_Bs:
145                 case irm_Hs:
146                         return 1;
147                 case irm_Iu:
148                 case irm_P:
149                 {
150                         unsigned char val2 = get_tarval_sub_bits(tv_const, 2);
151                         unsigned char val3 = get_tarval_sub_bits(tv_const, 3);
152                         if (val2 || val3)
153                                 return 0;
154
155                         // fall through
156                 }
157                 case irm_Hu:
158                 {
159                         unsigned char val1 = get_tarval_sub_bits(tv_const, 1);
160                         if (val1&0x80)
161                                 return 0;
162                         return 1;
163                 }
164
165                 case irm_Is:
166                 {
167                         unsigned char val2 = get_tarval_sub_bits(tv_const, 2);
168                         unsigned char val3 = get_tarval_sub_bits(tv_const, 3);
169                         if (val2==0 && val3==0)
170                         {
171                                 unsigned char val1 = get_tarval_sub_bits(tv_const, 1);
172                                 if (val1&0x80)
173                                         return 0;
174                                 return 1;
175                         }
176                         if (!(val2==0xff && val3==0xff))
177                         {
178                                 unsigned char val1 = get_tarval_sub_bits(tv_const, 1);
179                                 if (!(val1&0x80))
180                                         return 0;
181                                 return 1;
182                         }
183                         return 0;
184                 }
185                 default:
186                         panic("is_16bit_signed_const(): Mode not supported: %F", get_irn_mode(node));
187         }
188 }
189
190 /**
191  * Returns true, if the given node is a Const node and it's value fits into
192  * a unsigned 16-bit variable
193  */
194 static int is_16bit_unsigned_const(ir_node *node)
195 {
196         tarval *tv_const;
197
198         if (!is_ppc32_Const(node)) return 0;
199
200         tv_const = get_ppc32_constant_tarval(node);
201         switch (get_nice_modecode(get_irn_mode(node)))
202         {
203                 case irm_Bu:
204                 case irm_Bs:
205                 case irm_Hs:
206                 case irm_Hu:
207                         return 1;
208                 case irm_Iu:
209                 case irm_P:
210                 case irm_Is:
211                 {
212                         unsigned char val2 = get_tarval_sub_bits(tv_const, 2);
213                         unsigned char val3 = get_tarval_sub_bits(tv_const, 3);
214                         if (val2 || val3)
215                                 return 0;
216                         return 1;
217                 }
218                 default:
219                         panic("is_16bit_unsigned_const(): Mode not supported: %F", get_irn_mode(node));
220         }
221 }
222
223
224 /****************************************************************************************************
225  *                  _        _                        __                           _   _
226  *                 | |      | |                      / _|                         | | (_)
227  *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
228  * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
229  * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
230  * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
231  *
232  ****************************************************************************************************/
233
234 /**
235  * Creates an ppc Add.
236  *
237  * @param env   The transformation environment
238  * @return the created ppc Add node
239  */
240 static ir_node *gen_Add(ppc32_transform_env_t *env)
241 {
242         ir_node *op1 = get_Add_left(env->irn);
243         ir_node *op2 = get_Add_right(env->irn);
244
245         switch (get_nice_modecode(env->mode)){
246                 case irm_D:
247                         return new_bd_ppc32_fAdd(env->dbg, env->block, op1, op2, env->mode);
248                 case irm_F:
249                         return new_bd_ppc32_fAdds(env->dbg, env->block, op1, op2, env->mode);
250                 case irm_Is:
251                 case irm_Iu:
252                 case irm_Hs:
253                 case irm_Hu:
254                 case irm_Bs:
255                 case irm_Bu:
256                 case irm_P:
257                         if (is_16bit_signed_const(op1))
258                         {
259                                 ir_node *addnode = new_bd_ppc32_Addi(env->dbg, env->block, op2, env->mode);
260                                 set_ppc32_constant_tarval(addnode, get_ppc32_constant_tarval(op1));
261                                 set_ppc32_offset_mode(addnode, ppc32_ao_None);
262                                 return addnode;
263                         }
264                         if (is_16bit_signed_const(op2))
265                         {
266                                 ir_node *addnode = new_bd_ppc32_Addi(env->dbg, env->block, op1, env->mode);
267                                 set_ppc32_constant_tarval(addnode, get_ppc32_constant_tarval(op2));
268                                 set_ppc32_offset_mode(addnode, ppc32_ao_None);
269                                 return addnode;
270                         }
271
272                         return new_bd_ppc32_Add(env->dbg, env->block, op1, op2, env->mode);
273
274                 default:
275                         panic("Mode for Add not supported: %F", env->mode);
276         }
277 }
278
279 /**
280  * Creates an ppc Mul.
281  *
282  * @param env   The transformation environment
283  * @return the created ppc Mul node
284  */
285 static ir_node *gen_Mul(ppc32_transform_env_t *env)
286 {
287         ir_node *op1 = get_Mul_left(env->irn);
288         ir_node *op2 = get_Mul_right(env->irn);
289
290         switch (get_nice_modecode(env->mode)){
291                 case irm_D:
292                         return new_bd_ppc32_fMul(env->dbg, env->block, op1, op2, env->mode);
293                 case irm_F:
294                         return new_bd_ppc32_fMuls(env->dbg, env->block, op1, op2, env->mode);
295                 case irm_Is:
296                 case irm_Iu:
297                 case irm_Hs:
298                 case irm_Hu:
299                 case irm_Bs:
300                 case irm_Bu:
301                         return new_bd_ppc32_Mullw(env->dbg, env->block, op1, op2, env->mode);
302
303                 case irm_P:
304                 default:
305                         panic("Mode for Mul not supported: %F", env->mode);
306         }
307 }
308
309 /**
310  * Creates an ppc Mulh.
311  *
312  * @param env   The transformation environment
313  * @return the created ppc Mulh node
314  */
315 static ir_node *gen_Mulh(ppc32_transform_env_t *env)
316 {
317         ir_node *op1 = get_irn_n(env->irn, 0);
318         ir_node *op2 = get_irn_n(env->irn, 1);
319
320         switch (get_nice_modecode(env->mode)){
321                 case irm_Is:
322                 case irm_Hs:
323                 case irm_Bs:
324                         return new_bd_ppc32_Mulhw(env->dbg, env->block, op1, op2, env->mode);
325
326                 case irm_Iu:
327                 case irm_Hu:
328                 case irm_Bu:
329                         return new_bd_ppc32_Mulhwu(env->dbg, env->block, op1, op2, env->mode);
330
331                 case irm_D:
332                 case irm_F:
333                 case irm_P:
334                 default:
335                         panic("Mode for Mulh not supported: %F", env->mode);
336         }
337 }
338
339 /**
340  * Creates an ppc And.
341  *
342  * @param env   The transformation environment
343  * @return the created ppc And node
344  */
345 static ir_node *gen_And(ppc32_transform_env_t *env)
346 {
347         ir_node *op1 = get_And_left(env->irn);
348         ir_node *op2 = get_And_right(env->irn);
349
350         return new_bd_ppc32_And(env->dbg, env->block, op1, op2, env->mode);
351 }
352
353 /**
354  * Creates an ppc Or.
355  *
356  * @param env   The transformation environment
357  * @return the created ppc Or node
358  */
359 static ir_node *gen_Or(ppc32_transform_env_t *env)
360 {
361         ir_node *op1 = get_Or_left(env->irn);
362         ir_node *op2 = get_Or_right(env->irn);
363
364         return new_bd_ppc32_Or(env->dbg, env->block, op1, op2, env->mode);
365 }
366
367 /**
368  * Creates an ppc Xor.
369  *
370  * @param env   The transformation environment
371  * @return the created ppc Xor node
372  */
373 static ir_node *gen_Eor(ppc32_transform_env_t *env)
374 {
375         ir_node *op1 = get_Eor_left(env->irn);
376         ir_node *op2 = get_Eor_right(env->irn);
377
378         return new_bd_ppc32_Xor(env->dbg, env->block, op1, op2, env->mode);
379 }
380
381 /**
382  * Creates an ppc Sub.
383  *
384  * @param env   The transformation environment
385  * @return the created ppc Sub node
386  */
387 static ir_node *gen_Sub(ppc32_transform_env_t *env)
388 {
389         ir_node *op1 = get_Sub_left(env->irn);
390         ir_node *op2 = get_Sub_right(env->irn);
391
392         switch (get_nice_modecode(env->mode)){
393                 case irm_D:
394                         return new_bd_ppc32_fSub(env->dbg, env->block, op1, op2, env->mode);
395                 case irm_F:
396                         return new_bd_ppc32_fSubs(env->dbg, env->block, op1, op2, env->mode);
397                 case irm_Is:
398                 case irm_Iu:
399                 case irm_Hs:
400                 case irm_Hu:
401                 case irm_Bs:
402                 case irm_Bu:
403                 case irm_P:
404                         return new_bd_ppc32_Sub(env->dbg, env->block, op1, op2, env->mode);
405
406                 default:
407                         panic("Mode for Sub not supported: %F", env->mode);
408         }
409 }
410
411 /**
412  * Creates an ppc floating Div.
413  *
414  * @param env   The transformation environment
415  * @return the created ppc fDiv node
416  */
417 static ir_node *gen_Quot(ppc32_transform_env_t *env)
418 {
419         ir_node *op1 = get_Quot_left(env->irn);
420         ir_node *op2 = get_Quot_right(env->irn);
421
422         switch (get_nice_modecode(env->mode)){
423                 case irm_D:
424                         return new_bd_ppc32_fDiv(env->dbg, env->block, op1, op2, env->mode);
425                 case irm_F:
426                         return new_bd_ppc32_fDivs(env->dbg, env->block, op1, op2, env->mode);
427
428                 default:
429                         panic("Mode for Quot not supported: %F", env->mode);
430         }
431 }
432
433 /**
434  * Creates an ppc integer Div.
435  *
436  * @param env   The transformation environment
437  * @return the created ppc Div node
438  */
439 static ir_node *gen_Div(ppc32_transform_env_t *env)
440 {
441         ir_node *op1 = get_Div_left(env->irn);
442         ir_node *op2 = get_Div_right(env->irn);
443
444         switch (get_nice_modecode(get_irn_mode(op1))){
445                 case irm_Is:
446                 case irm_Hs:
447                 case irm_Bs:
448                         return new_bd_ppc32_Divw(env->dbg, env->block, op1, op2, mode_T);
449
450                 case irm_Iu:
451                 case irm_Hu:
452                 case irm_Bu:
453                         return new_bd_ppc32_Divwu(env->dbg, env->block, op1, op2, mode_T);
454
455                 default:
456                         panic("Mode for Div not supported: %F", get_irn_mode(op1));
457         }
458 }
459
460 /**
461  * Creates an ppc integer Div and Mod.
462  *
463  * @param env   The transformation environment
464  * @return the created ppc Div node
465  */
466 static ir_node *gen_DivMod(ppc32_transform_env_t *env)
467 {
468         ir_node *op1 = get_DivMod_left(env->irn);
469         ir_node *op2 = get_DivMod_right(env->irn);
470         ir_node *proj_div = NULL, *proj_mod = NULL;
471         ir_node *div_result;
472         const ir_edge_t *edge;
473         ir_mode *res_mode;
474
475         foreach_out_edge(env->irn, edge)
476         {
477                 if (is_Proj(edge->src))
478                 {
479                         switch (get_Proj_proj(edge->src)){
480                                 case pn_DivMod_res_div:
481                                         proj_div = edge->src;
482                                         break;
483                                 case pn_DivMod_res_mod:
484                                         proj_mod = edge->src;
485                                         break;
486                                 default:
487                                         break;
488                         }
489                 }
490         }
491
492         assert(proj_div!=NULL || proj_mod!=NULL);
493
494         res_mode = get_irn_mode(proj_div);
495
496         switch (get_nice_modecode(res_mode))
497         {
498                 case irm_Is:
499                 case irm_Hs:
500                 case irm_Bs:
501                         div_result = new_bd_ppc32_Divw(env->dbg, env->block, op1, op2, mode_T);
502                         break;
503
504                 case irm_Iu:
505                 case irm_Hu:
506                 case irm_Bu:
507                         div_result = new_bd_ppc32_Divwu(env->dbg, env->block, op1, op2, mode_T);
508                         break;
509
510                 default:
511                         panic("Mode for DivMod not supported: %F", res_mode);
512         }
513
514         if (proj_div == NULL)
515                 proj_div = new_rd_Proj(env->dbg, div_result, get_irn_mode(proj_mod), pn_DivMod_res_div);
516
517         if (proj_mod!=NULL){
518                 ir_node *mul_result;
519                 ir_node *mod_result;
520
521                 mul_result = new_bd_ppc32_Mullw(env->dbg, env->block, proj_div, op2, res_mode);
522                 mod_result = new_bd_ppc32_Sub(env->dbg, env->block, op1, mul_result, res_mode);
523
524                 exchange(proj_mod, mod_result);
525         }
526
527         return div_result;
528 }
529
530 /**
531  * Creates an ppc integer Mod.
532  *
533  * @param env   The transformation environment
534  * @return the created ppc Mod result node
535  */
536 static ir_node *gen_Mod(ppc32_transform_env_t *env)
537 {
538         ir_node *op1 = get_Mod_left(env->irn);
539         ir_node *op2 = get_Mod_right(env->irn);
540         ir_node *proj_div = NULL, *proj_mod = NULL;
541         ir_node *div_result;
542         ir_mode *res_mode;
543         ir_node *mul_result;
544         ir_node *mod_result;
545
546         proj_mod = get_succ_Proj(env->irn, pn_Mod_res);
547
548         assert(proj_mod != NULL);
549         res_mode = get_irn_mode(proj_mod);
550
551         switch (get_nice_modecode(res_mode))
552         {
553                 case irm_Is:
554                 case irm_Hs:
555                 case irm_Bs:
556                         div_result = new_bd_ppc32_Divw(env->dbg, env->block, op1, op2, mode_T);
557                         break;
558
559                 case irm_Iu:
560                 case irm_Hu:
561                 case irm_Bu:
562                         div_result = new_bd_ppc32_Divwu(env->dbg, env->block, op1, op2, mode_T);
563                         break;
564
565                 default:
566                         panic("Mode for Mod not supported: %s\n", get_mode_name(res_mode));
567         }
568
569         proj_div = new_rd_Proj(env->dbg, div_result, res_mode, pn_DivMod_res_div);
570
571         mul_result = new_bd_ppc32_Mullw(env->dbg, env->block, proj_div, op2, res_mode);
572         mod_result = new_bd_ppc32_Sub(env->dbg, env->block, op1, mul_result, res_mode);
573
574         exchange(proj_mod, mod_result);
575
576         return div_result;
577 }
578
579 /**
580  * Creates an ppc Shl.
581  *
582  * @param env   The transformation environment
583  * @return the created ppc Shl node
584  */
585 static ir_node *gen_Shl(ppc32_transform_env_t *env)
586 {
587         ir_node *op1 = get_Shl_left(env->irn);
588         ir_node *op2 = get_Shl_right(env->irn);
589
590         if (is_ppc32_Const(op2))
591         {
592                 ir_node *shift = new_bd_ppc32_Rlwinm(env->dbg, env->block, op1, env->mode);
593                 tarval *tv_const = get_ppc32_constant_tarval(op2);
594                 int sh = get_tarval_long(tv_const);
595                 assert(0<=sh && sh<=31);
596                 set_ppc32_rlwimi_const(shift, sh, 0, 31-sh);
597                 return shift;
598         }
599         return new_bd_ppc32_Slw(env->dbg, env->block, op1, op2, env->mode);
600 }
601
602 /**
603  * Creates an ppc Srw.
604  *
605  * @param env   The transformation environment
606  * @return the created ppc Shr node
607  */
608 static ir_node *gen_Shr(ppc32_transform_env_t *env)
609 {
610         ir_node *op1 = get_Shr_left(env->irn);
611         ir_node *op2 = get_Shr_right(env->irn);
612
613         if (is_ppc32_Const(op2))
614         {
615                 ir_node *shift = new_bd_ppc32_Rlwinm(env->dbg, env->block, op1, env->mode);
616                 tarval *tv_const = get_ppc32_constant_tarval(op2);
617                 int sh = get_tarval_long(tv_const);
618                 assert(0<=sh && sh<=31);
619                 set_ppc32_rlwimi_const(shift, 32-sh, sh, 31);
620                 return shift;
621         }
622         return new_bd_ppc32_Srw(env->dbg, env->block, op1, op2, env->mode);
623 }
624
625 /**
626  * Creates an ppc Sraw.
627  *
628  * @param env   The transformation environment
629  * @return the created ppc Sraw node
630  */
631 static ir_node *gen_Shrs(ppc32_transform_env_t *env)
632 {
633         ir_node *op1 = get_Shrs_left(env->irn);
634         ir_node *op2 = get_Shrs_right(env->irn);
635
636         if (is_ppc32_Const(op2))
637         {
638                 ir_node *shift = new_bd_ppc32_Srawi(env->dbg, env->block, op1, env->mode);
639                 tarval *tv_const = get_ppc32_constant_tarval(op2);
640                 int sh = get_tarval_long(tv_const);
641                 assert(0<=sh && sh<=31);
642                 (void) sh;
643                 set_ppc32_constant_tarval(shift, tv_const);
644                 set_ppc32_offset_mode(shift, ppc32_ao_None);
645                 return shift;
646         }
647         return new_bd_ppc32_Sraw(env->dbg, env->block, op1, op2, env->mode);
648 }
649
650 /**
651  * Creates an ppc Rotl.
652  *
653  * @param env   The transformation environment
654  * @return the created ppc Rotl node
655  */
656 static ir_node *gen_Rotl(ppc32_transform_env_t *env)
657 {
658         ir_node *op1 = get_Rotl_left(env->irn);
659         ir_node *op2 = get_Rotl_right(env->irn);
660
661         if (is_ppc32_Const(op2))
662         {
663                 ir_node *rot = new_bd_ppc32_Rlwinm(env->dbg, env->block, op1, env->mode);
664                 tarval *tv_const = get_ppc32_constant_tarval(op2);
665                 int sh = get_tarval_long(tv_const);
666                 assert(0<=sh && sh<=31);
667                 set_ppc32_rlwimi_const(rot, sh, 0, 31);
668                 return rot;
669         }
670         return new_bd_ppc32_Rlwnm(env->dbg, env->block, op1, op2, env->mode);
671 }
672
673 /**
674  * Creates an ppc Cmp.
675  *
676  * @param env   The transformation environment
677  * @return the created ppc Cmp node
678  */
679 static ir_node *gen_Cmp(ppc32_transform_env_t *env)
680 {
681         ir_node *op1 = get_Cmp_left(env->irn);
682         ir_node *op2 = get_Cmp_right(env->irn);
683
684         const ir_edge_t *edge;
685         foreach_out_edge(env->irn, edge)
686         {
687                 if (is_Proj(edge->src))
688                         set_irn_mode(edge->src, get_ppc32_mode_Cond());
689         }
690
691         if (mode_is_float(env->mode))
692                 return new_bd_ppc32_fCmpu(env->dbg, env->block, op1, op2, env->mode);
693         else if (mode_is_signed(env->mode))
694         {
695                 if (is_16bit_signed_const(op2))
696                 {
697                         ir_node *cmp = new_bd_ppc32_Cmpi(env->dbg, env->block, op1, env->mode);
698                         tarval *tv_const = get_ppc32_constant_tarval(op2);
699                         set_ppc32_constant_tarval(cmp, tv_const);
700                         set_ppc32_offset_mode(cmp, ppc32_ao_None);
701                         return cmp;
702                 }
703                 else
704                 {
705                         return new_bd_ppc32_Cmp(env->dbg, env->block, op1, op2, env->mode);
706                 }
707         }
708         else
709         {
710                 if (is_16bit_unsigned_const(op2))
711                 {
712                         ir_node *cmp = new_bd_ppc32_Cmpli(env->dbg, env->block, op1, env->mode);
713                         tarval *tv_const = get_ppc32_constant_tarval(op2);
714                         set_ppc32_constant_tarval(cmp, tv_const);
715                         set_ppc32_offset_mode(cmp, ppc32_ao_None);
716
717                         return cmp;
718                 }
719                 else
720                 {
721                         return new_bd_ppc32_Cmpl(env->dbg, env->block, op1, op2, env->mode);
722                 }
723         }
724 }
725
726 /**
727  * Transforms a Minus node.
728  *
729  * @param env   The transformation environment
730  * @return the created ppc Minus node
731  */
732 static ir_node *gen_Minus(ppc32_transform_env_t *env)
733 {
734         ir_node *op = get_Minus_op(env->irn);
735
736         switch (get_nice_modecode(env->mode)){
737                 case irm_D:
738                 case irm_F:
739                         return new_bd_ppc32_fNeg(env->dbg, env->block, op, env->mode);
740                 case irm_Is:
741                 case irm_Iu:
742                 case irm_Hs:
743                 case irm_Hu:
744                 case irm_Bs:
745                 case irm_Bu:
746                 case irm_P:
747                         return new_bd_ppc32_Neg(env->dbg, env->block, op, env->mode);
748
749                 default:
750                         panic("Mode for Neg not supported: %F", env->mode);
751         }
752 }
753
754 /**
755  * Transforms a Not node.
756  *
757  * @param env   The transformation environment
758  * @return the created ppc Not node
759  */
760 static ir_node *gen_Not(ppc32_transform_env_t *env)
761 {
762         return new_bd_ppc32_Not(env->dbg, env->block, get_Not_op(env->irn), env->mode);
763 }
764
765
766 static ir_node *own_gen_Andi_dot_lo16(ppc32_transform_env_t *env, ir_node *op, int mask)
767 {
768         ir_node *andi = new_bd_ppc32_Andi_dot(env->dbg, env->block, op, mode_T);
769         ir_node* in[1];
770         set_ppc32_offset_mode(andi, ppc32_ao_Lo16);
771         set_ppc32_constant_tarval(andi, new_tarval_from_long(mask, mode_Is));
772         in[0] = new_rd_Proj(env->dbg, andi, env->mode,1);
773         be_new_Keep(env->block, 1, in);
774         return new_rd_Proj(env->dbg, andi, env->mode,0);
775 }
776
777 /**
778  * Transforms a Conv node.
779  *
780  * @param env   The transformation environment
781  * @return the created ppc Conv node
782  */
783 static ir_node *gen_Conv(ppc32_transform_env_t *env)
784 {
785         ir_node *op = get_Conv_op(env->irn);
786         ppc32_modecode from_mode=get_nice_modecode(get_irn_mode(op));
787         ppc32_modecode to_mode=get_nice_modecode(env->mode);
788
789 #define SKIP return op
790
791         if (from_mode == to_mode) SKIP;
792
793         switch (from_mode){
794                 case irm_F:
795                         switch (to_mode)
796                         {
797                                 case irm_D: SKIP;
798                                 default:
799                                         break;
800                         }
801                         break;
802
803                 case irm_D:
804                         switch (to_mode)
805                         {
806                                 case irm_F:
807                                         return new_bd_ppc32_fRsp(env->dbg, env->block, op, env->mode);
808                                 default:
809                                         break;
810                         }
811                         break;
812
813                 case irm_Is:
814                 case irm_Iu:
815                         switch (to_mode)
816                         {
817                                 case irm_Hs:
818                                         return new_bd_ppc32_Extsh(env->dbg, env->block, op, env->mode);
819                                 case irm_Hu:
820                                         return own_gen_Andi_dot_lo16(env, op, 0xffff);
821                                 case irm_Bs:
822                                         return new_bd_ppc32_Extsb(env->dbg, env->block, op, env->mode);
823                                 case irm_Bu:
824                                         return own_gen_Andi_dot_lo16(env, op, 0xff);
825                                 case irm_Is:
826                                 case irm_Iu:
827                                         SKIP;
828                                 default:
829                                         break;
830                         }
831                         break;
832
833                 case irm_Hs:
834                 case irm_Hu:
835                         switch (to_mode)
836                         {
837                                 case irm_Iu:
838                                         if (from_mode==irm_Hu)
839                                 case irm_Hu:
840                                                 return own_gen_Andi_dot_lo16(env, op, 0xffff);
841                                 case irm_Is:
842                                         SKIP;
843                                 case irm_Bs:
844                                         return new_bd_ppc32_Extsb(env->dbg, env->block, op, env->mode);
845                                 case irm_Bu:
846                                         return own_gen_Andi_dot_lo16(env, op, 0xff);
847                                 case irm_Hs:
848                                         return new_bd_ppc32_Extsh(env->dbg, env->block, op, env->mode);
849                                 default:
850                                         break;
851                         }
852                         break;
853
854                 case irm_Bs:
855                 case irm_Bu:
856                         switch (to_mode)
857                         {
858                                 case irm_Iu:
859                                 case irm_Hu:
860                                         if (from_mode==irm_Bs)
861                                 case irm_Bu:
862                                                 return own_gen_Andi_dot_lo16(env, op, 0xff);
863                                 case irm_Is:
864                                 case irm_Hs:
865                                         SKIP;
866                                 case irm_Bs:
867                                         return new_bd_ppc32_Extsb(env->dbg, env->block, op, env->mode);
868                                 default:
869                                         break;
870                         }
871                         break;
872                 case irm_P:
873                         if (to_mode==irm_Is || to_mode==irm_Iu) SKIP;
874                         break;
875                 default:
876                         break;
877         }
878
879         panic("Mode for Conv not supported: %F -> %F", get_irn_mode(op), env->mode);
880 #undef SKIP
881 }
882
883 /**
884  * Transforms an Abs node.
885  *
886  * @param env   The transformation environment
887  * @return the ppc node generating the absolute value
888  */
889 static ir_node *gen_Abs(ppc32_transform_env_t *env)
890 {
891         ir_node *op = get_Abs_op(env->irn);
892         int shift = 7;
893         ir_node *n1,*n2;
894
895         switch (get_nice_modecode(env->mode))
896         {
897                 case irm_F:
898                 case irm_D:
899                         return new_bd_ppc32_fAbs(env->dbg, env->block, op, env->mode);
900                 case irm_Is:
901                         shift += 16;
902                 case irm_Hs:
903                         shift += 8;
904                 case irm_Bs:
905                         n1 = new_bd_ppc32_Srawi(env->dbg, env->block, op, env->mode);
906                         set_ppc32_constant_tarval(n1, new_tarval_from_long(shift, mode_Is));
907                         set_ppc32_offset_mode(n1, ppc32_ao_None);
908                         n2 = new_bd_ppc32_Add(env->dbg, env->block, op, n1, env->mode);
909                         return new_bd_ppc32_Xor(env->dbg, env->block, n2, n1, env->mode);
910                 default:
911                         break;
912         }
913         panic("Mode for Abs not supported: %F", env->mode);
914 }
915
916 /**
917  * Transforms an Cond node.
918  *
919  * @param env   The transformation environment
920  * @return a ppc branch node
921  */
922 static ir_node *gen_Cond(ppc32_transform_env_t *env)
923 {
924         ir_node *selector = get_Cond_selector(env->irn);
925         ir_mode *projmode = get_irn_mode(selector);
926         if (is_Proj(selector) && projmode==get_ppc32_mode_Cond())
927         {
928                 int projnum = get_Proj_proj(selector);
929                 ir_node *branch = new_bd_ppc32_Branch(env->dbg, env->block, selector, env->mode);
930                 set_ppc32_proj_nr(branch, projnum);
931                 return branch;
932         }
933         else
934         {
935                 ir_node *unknown_gpr = new_bd_ppc32_Unknown(env->dbg, env->block, mode_Is);
936                 ir_node *unknown_cond = new_bd_ppc32_cUnknown(env->dbg, env->block, get_ppc32_mode_Cond());
937
938                 ir_node *switch_node = new_bd_ppc32_Switch(env->dbg, env->block, selector,
939                         unknown_gpr, unknown_cond, env->mode);
940                 set_ppc32_proj_nr(switch_node, get_Cond_default_proj(env->irn));
941
942                 return switch_node;
943         }
944 }
945
946 /**
947  * Transforms an Unknown node.
948  *
949  * @param env   The transformation environment
950  * @return a ppc Unknown node
951  */
952 static ir_node *gen_Unknown(ppc32_transform_env_t *env)
953 {
954         if (mode_is_float(env->mode))
955                 return new_bd_ppc32_fUnknown(env->dbg, env->block, env->mode);
956         else if (mode_is_int(env->mode))
957                 return new_bd_ppc32_Unknown(env->dbg, env->block, env->mode);
958         else
959                 panic("Mode %F for unknown value not supported.", env->mode);
960 }
961
962 static ir_node *ldst_insert_const(ir_node *ptr, tarval **ptv, ident **pid, ppc32_transform_env_t *env)
963 {
964         tarval *tv_const = NULL;
965         ident *id_symconst = NULL;
966
967         if (is_ppc32_Const(ptr))
968         {
969                 tv_const = get_ppc32_constant_tarval(ptr);
970                 ptr = new_bd_ppc32_Addis_zero(env->dbg, env->block, mode_P, ppc32_ao_Ha16, tv_const, NULL);
971         }
972         else if (is_ppc32_SymConst(ptr))
973         {
974 #if 0
975                 ir_entity *ent = get_ppc32_frame_entity(ptr);
976                 if (is_direct_entity(ent))
977                 {
978                         id_symconst = get_entity_ident(ent);
979                         ptr = new_bd_ppc32_Addis_zero(env->dbg, env->block, mode_P, ppc32_ao_Ha16, NULL, id_symconst);
980                 }
981 #endif
982         }
983         *ptv = tv_const;
984         *pid = id_symconst;
985         return ptr;
986 }
987
988 /**
989  * Transforms a Load.
990  *
991  * @param env   The transformation environment
992  * @return the created ppc Load node
993  */
994 static ir_node *gen_Load(ppc32_transform_env_t *env)
995 {
996         ir_node *node = env->irn;
997         ir_node *loadptr = get_Load_ptr(node);
998         ir_node *load;
999         ir_mode *mode = get_Load_mode(node);
1000         tarval *tv_const = NULL;
1001         ident *id_symconst = NULL;
1002
1003         loadptr = ldst_insert_const(loadptr, &tv_const, &id_symconst, env);
1004         switch (get_nice_modecode(mode)){
1005                 case irm_Bu:
1006                         load = new_bd_ppc32_Lbz(env->dbg, env->block, loadptr, get_Load_mem(node));
1007                         break;
1008
1009                 case irm_Bs:
1010                 {
1011                         ir_node *proj_load, *extsb_node;
1012                         load =  new_bd_ppc32_Lbz(env->dbg, env->block, loadptr, get_Load_mem(node));
1013                         proj_load = new_rd_Proj(env->dbg, load, mode, pn_Load_res);
1014                         extsb_node = new_bd_ppc32_Extsb(env->dbg, env->block, proj_load, mode);
1015                         exchange(get_succ_Proj(env->irn, pn_Load_res), extsb_node);
1016                         break;
1017                 }
1018
1019
1020                 case irm_Hu:
1021                         load = new_bd_ppc32_Lhz(env->dbg, env->block, loadptr, get_Load_mem(node));
1022                         break;
1023                 case irm_Hs:
1024                         load =new_bd_ppc32_Lha(env->dbg, env->block, loadptr, get_Load_mem(node));
1025                         break;
1026                 case irm_Is:
1027                 case irm_Iu:
1028                 case irm_P:
1029                         load = new_bd_ppc32_Lwz(env->dbg, env->block, loadptr, get_Load_mem(node));
1030                         break;
1031
1032                 case irm_D:
1033                         load = new_bd_ppc32_Lfd(env->dbg, env->block, loadptr, get_Load_mem(node));
1034                         break;
1035                 case irm_F:
1036                         load = new_bd_ppc32_Lfs(env->dbg, env->block, loadptr, get_Load_mem(node));
1037                         break;
1038
1039                 default:
1040                         panic("Mode for Load not supported: %F", env->mode);
1041         }
1042
1043         if (tv_const)
1044         {
1045                 set_ppc32_offset_mode(load, ppc32_ao_Lo16);
1046                 set_ppc32_constant_tarval(load, tv_const);
1047         }
1048         else if (id_symconst)
1049         {
1050                 set_ppc32_offset_mode(load, ppc32_ao_Lo16);
1051                 set_ppc32_symconst_ident(load, id_symconst);
1052         }
1053         return load;
1054 }
1055
1056
1057
1058 /**
1059  * Transforms a Store.
1060  *
1061  * @param env   The transformation environment
1062  * @return the created ppc Store node
1063  */
1064 static ir_node *gen_Store(ppc32_transform_env_t *env)
1065 {
1066         ir_node *node = env->irn;
1067         ir_node *storeptr = get_Store_ptr(node);
1068         ir_node *valuenode = get_Store_value(node);
1069         ir_mode *mode = get_irn_mode(valuenode);
1070         ir_node *store;
1071         tarval *tv_const = NULL;
1072         ident *id_symconst = NULL;
1073
1074         storeptr = ldst_insert_const(storeptr, &tv_const, &id_symconst, env);
1075
1076         switch (get_nice_modecode(mode)){
1077                 case irm_Bu:
1078                 case irm_Bs:
1079                         store = new_bd_ppc32_Stb(env->dbg, env->block, storeptr, get_Store_value(node), get_Store_mem(node));
1080                         break;
1081
1082                 case irm_Hu:
1083                 case irm_Hs:
1084                         store = new_bd_ppc32_Sth(env->dbg, env->block, storeptr, get_Store_value(node), get_Store_mem(node));
1085                         break;
1086                 case irm_Is:
1087                 case irm_Iu:
1088                 case irm_P:
1089                         store = new_bd_ppc32_Stw(env->dbg, env->block, storeptr, get_Store_value(node), get_Store_mem(node));
1090                         break;
1091
1092                 case irm_D:
1093                         store = new_bd_ppc32_Stfd(env->dbg, env->block, storeptr, get_Store_value(node), get_Store_mem(node));
1094                         break;
1095                 case irm_F:
1096                         store = new_bd_ppc32_Stfs(env->dbg, env->block, storeptr, get_Store_value(node), get_Store_mem(node));
1097                         break;
1098
1099                 default:
1100                         panic("Mode for Store not supported: %F", env->mode);
1101         }
1102         if (tv_const)
1103         {
1104                 set_ppc32_offset_mode(store, ppc32_ao_Lo16);
1105                 set_ppc32_constant_tarval(store, tv_const);
1106         }
1107         else if (id_symconst)
1108         {
1109                 set_ppc32_offset_mode(store, ppc32_ao_Lo16);
1110                 set_ppc32_symconst_ident(store, id_symconst);
1111         }
1112         return store;
1113 }
1114
1115 /**
1116  * Transforms a CopyB.
1117  *
1118  * @param env   The transformation environment
1119  * @return the created ppc CopyB node
1120  */
1121 static ir_node *gen_CopyB(ppc32_transform_env_t *env)
1122 {
1123         ir_node *mem = get_CopyB_mem(env->irn);
1124         ir_node *src = get_CopyB_src(env->irn);
1125         ir_node *dest = get_CopyB_dst(env->irn);
1126         ir_type *type = get_CopyB_type(env->irn);
1127         int size = get_type_size_bytes(type);
1128         int offset = 0;
1129
1130         ir_node *load, *store = NULL;
1131
1132         if (size/4 >= 1)
1133         {
1134                 ir_node *res;
1135                 tarval *offset0 = new_tarval_from_long(0, mode_Is);
1136                 tarval *offset4 = new_tarval_from_long(4, mode_Is);
1137
1138                 load = new_bd_ppc32_Lwz(env->dbg, env->block, src, mem);
1139                 set_ppc32_constant_tarval(load, offset0);
1140                 set_ppc32_offset_mode(load, ppc32_ao_None);
1141                 mem = new_rd_Proj(env->dbg, load, mode_M, pn_Load_M);
1142                 res = new_rd_Proj(env->dbg, load, mode_Is, pn_Load_res);
1143
1144                 store = new_bd_ppc32_Stw(env->dbg, env->block, dest, res, mem);
1145                 set_ppc32_constant_tarval(store, offset0);
1146                 set_ppc32_offset_mode(store, ppc32_ao_None);
1147                 mem = new_rd_Proj(env->dbg, store, mode_M, pn_Store_M);
1148
1149                 if (size/4==2)
1150                 {
1151                         load = new_bd_ppc32_Lwz(env->dbg, env->block, src, mem);
1152                         set_ppc32_constant_tarval(load, offset4);
1153                         set_ppc32_offset_mode(load, ppc32_ao_None);
1154                         mem = new_rd_Proj(env->dbg, load, mode_M, pn_Load_M);
1155                         res = new_rd_Proj(env->dbg, load, mode_Is, pn_Load_res);
1156
1157                         store = new_bd_ppc32_Stw(env->dbg, env->block, dest, res, mem);
1158                         set_ppc32_constant_tarval(store, offset4);
1159                         set_ppc32_offset_mode(store, ppc32_ao_None);
1160                         mem = new_rd_Proj(env->dbg, store, mode_M, pn_Store_M);
1161
1162                         offset = 8;
1163                 }
1164                 else
1165                 {
1166                         ir_node *ornode, *mtctrnode;
1167                         ir_node* in[3];
1168                         assert(size/4-1<=0xffff);
1169                         if (size/4-1<0x8000)
1170                         {
1171                                 ornode = new_bd_ppc32_Addi_zero(env->dbg, env->block, mode_Is);
1172                                 set_ppc32_offset_mode(ornode, ppc32_ao_None);
1173                         }
1174                         else
1175                         {
1176                                 ir_node *zeroreg = new_bd_ppc32_Addi_zero(env->dbg, env->block, mode_Is);
1177                                 set_ppc32_offset_mode(zeroreg, ppc32_ao_None);
1178                                 set_ppc32_constant_tarval(zeroreg, new_tarval_from_long(0, mode_Is));
1179                                 ornode = new_bd_ppc32_Ori(env->dbg, env->block, zeroreg, mode_Is);
1180                                 set_ppc32_offset_mode(ornode, ppc32_ao_Lo16);
1181                         }
1182
1183                         set_ppc32_constant_tarval(ornode, new_tarval_from_long(size/4-1, mode_Is));
1184                         mtctrnode = new_bd_ppc32_Mtctr(env->dbg, env->block, ornode, mode_Is);
1185                         store = new_bd_ppc32_LoopCopy(env->dbg, env->block, src, dest, mtctrnode, mem, mode_T);
1186
1187                         in[0] = new_rd_Proj(env->dbg, store, mode_Is, 1); // src
1188                         in[1] = new_rd_Proj(env->dbg, store, mode_Is, 2);       // dest
1189                         in[2] = new_rd_Proj(env->dbg, store, mode_Is, 4);       // temp
1190                         be_new_Keep(env->block, 3, in);
1191                         in[0] = new_rd_Proj(env->dbg, store, mode_Is, 3); // ctr
1192                         be_new_Keep(env->block, 1, in);
1193
1194                         mem = new_rd_Proj(env->dbg, store, mode_M, 0);
1195
1196                         offset = 4;
1197                 }
1198         }
1199
1200         if (size & 2)
1201         {
1202                 ir_node *res;
1203                 tarval* offset_tarval = new_tarval_from_long(offset, mode_Is);
1204                 load = new_bd_ppc32_Lhz(env->dbg, env->block, src, mem);
1205                 set_ppc32_constant_tarval(load, offset_tarval);
1206                 set_ppc32_offset_mode(load, ppc32_ao_None);
1207                 mem = new_rd_Proj(env->dbg, load, mode_M, pn_Load_M);
1208                 res = new_rd_Proj(env->dbg, load, mode_Is, pn_Load_res);
1209
1210                 store = new_bd_ppc32_Sth(env->dbg, env->block, dest, res, mem);
1211                 set_ppc32_constant_tarval(store, offset_tarval);
1212                 set_ppc32_offset_mode(store, ppc32_ao_None);
1213                 mem = new_rd_Proj(env->dbg, store, mode_M, pn_Store_M);
1214
1215                 offset += 2;
1216         }
1217
1218         if (size & 1)
1219         {
1220                 ir_node *res;
1221                 tarval* offset_tarval = new_tarval_from_long(offset, mode_Is);
1222                 load = new_bd_ppc32_Lbz(env->dbg, env->block, src, mem);
1223                 set_ppc32_constant_tarval(load, offset_tarval);
1224                 set_ppc32_offset_mode(load, ppc32_ao_None);
1225                 mem = new_rd_Proj(env->dbg, load, mode_M, pn_Load_M);
1226                 res = new_rd_Proj(env->dbg, load, mode_Is, pn_Load_res);
1227
1228                 store = new_bd_ppc32_Stb(env->dbg, env->block, dest, res, mem);
1229                 set_ppc32_constant_tarval(store, offset_tarval);
1230                 set_ppc32_offset_mode(store, ppc32_ao_None);
1231                 // mem = new_rd_Proj(env->dbg, env->irg, store, mode_M, pn_Store_M);
1232         }
1233
1234         return store;
1235 }
1236
1237 /**
1238  * Transforms a FrameAddr into a ppc Add.
1239  *
1240  * @param env   The transformation environment
1241  */
1242 static ir_node *gen_be_FrameAddr(ppc32_transform_env_t *env)
1243 {
1244         ir_node *op = get_irn_n(env->irn, 0);
1245         ir_node *add = new_bd_ppc32_Addi(env->dbg, env->block, op, mode_P);
1246         set_ppc32_frame_entity(add, be_get_frame_entity(env->irn));
1247         return add;
1248 }
1249
1250
1251 /*********************************************************
1252  *                  _             _      _
1253  *                 (_)           | |    (_)
1254  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
1255  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
1256  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
1257  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
1258  *
1259  *********************************************************/
1260
1261 /**
1262  * the BAD transformer.
1263  */
1264 static ir_node *bad_transform(ppc32_transform_env_t *env)
1265 {
1266         panic("Transformation not implemented: %+F\n", env->irn);
1267 }
1268
1269 /**
1270  * Enters all transform functions into the generic pointer
1271  */
1272 void ppc32_register_transformers(void)
1273 {
1274         /* first clear the generic function pointer for all ops */
1275         clear_irp_opcodes_generic_func();
1276
1277 #define FIRM_OP(a)     op_##a->ops.generic = (op_func)gen_##a
1278 #define BAD(a)         op_##a->ops.generic = (op_func)bad_transform
1279 #define IGN(a)
1280
1281         FIRM_OP(Add);
1282         FIRM_OP(Mul);
1283         FIRM_OP(Mulh);
1284         FIRM_OP(And);
1285         FIRM_OP(Or);
1286         FIRM_OP(Eor);
1287
1288         FIRM_OP(Sub);
1289         FIRM_OP(Shl);
1290         FIRM_OP(Shr);
1291         FIRM_OP(Shrs);
1292         FIRM_OP(Rotl);
1293         FIRM_OP(Quot);
1294         FIRM_OP(Div);
1295         FIRM_OP(DivMod);
1296         FIRM_OP(Mod);
1297         FIRM_OP(Cmp);
1298
1299         FIRM_OP(Minus);
1300         FIRM_OP(Not);
1301         FIRM_OP(Conv);
1302         FIRM_OP(Abs);
1303
1304         FIRM_OP(Load);
1305         FIRM_OP(Store);
1306         FIRM_OP(Cond);
1307         FIRM_OP(Unknown);
1308         FIRM_OP(CopyB);
1309
1310         /* TODO: implement these nodes */
1311         BAD(Mux);
1312
1313         /* You probably don't need to handle the following nodes */
1314
1315         IGN(Call);
1316         IGN(Proj);
1317         IGN(Alloc);
1318
1319         IGN(Block);
1320         IGN(Start);
1321         IGN(End);
1322         IGN(NoMem);
1323         IGN(Phi);
1324         IGN(IJmp);
1325         IGN(Jmp);
1326         IGN(Break);
1327         IGN(Sync);
1328
1329         BAD(Raise);
1330         BAD(Sel);
1331         BAD(InstOf);
1332         BAD(Cast);
1333         BAD(Free);
1334         BAD(Tuple);
1335         BAD(Id);
1336         //BAD(Bad);
1337         BAD(Confirm);
1338         BAD(Filter);
1339         BAD(CallBegin);
1340         BAD(EndReg);
1341         BAD(EndExcept);
1342
1343         /* handle builtins */
1344         BAD(Builtin);
1345
1346         /* handle generic backend nodes */
1347         FIRM_OP(be_FrameAddr);
1348 }
1349
1350 typedef ir_node *(transform_func)(ppc32_transform_env_t *env);
1351
1352 /**
1353  * Transforms the given firm node (and maybe some other related nodes)
1354  * into one or more assembler nodes.
1355  *
1356  * @param node    the firm node
1357  * @param env     the debug module
1358  */
1359 void ppc32_transform_node(ir_node *node, void *env)
1360 {
1361         ppc32_code_gen_t *cg = (ppc32_code_gen_t *)env;
1362         ir_op *op            = get_irn_op(node);
1363         ir_node *asm_node    = NULL;
1364         (void) cg;
1365
1366         if (op == op_Block)
1367                 return;
1368
1369         DBG((cg->mod, LEVEL_1, "check %+F ... ", node));
1370
1371         if (op->ops.generic) {
1372                 ppc32_transform_env_t tenv;
1373                 transform_func *transform = (transform_func *)op->ops.generic;
1374
1375                 tenv.block    = get_nodes_block(node);
1376                 tenv.dbg      = get_irn_dbg_info(node);
1377                 tenv.irg      = current_ir_graph;
1378                 tenv.irn      = node;
1379                 tenv.mode     = get_irn_mode(node);
1380                 DEBUG_ONLY(tenv.mod = cg->mod;)
1381
1382                 asm_node = (*transform)(&tenv);
1383         }
1384
1385         if (asm_node) {
1386                 exchange(node, asm_node);
1387                 DB((cg->mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1388         }
1389         else {
1390                 DB((cg->mod, LEVEL_1, "ignored\n"));
1391         }
1392 }
1393
1394 /**
1395  * Constant generating code
1396  */
1397
1398 struct tv_ent {
1399         ir_entity *ent;
1400         tarval *tv;
1401 };
1402
1403 /** Compares two (entity, tarval) combinations */
1404 static int cmp_tv_ent(const void *a, const void *b, size_t len)
1405 {
1406         const struct tv_ent *e1 = a;
1407         const struct tv_ent *e2 = b;
1408         (void) len;
1409
1410         return !(e1->tv == e2->tv);
1411 }
1412
1413 /** Generates a SymConst node for a known FP const */
1414 static ir_node *gen_fp_known_symconst(ppc32_transform_env_t *env,
1415                                       tarval *known_const)
1416 {
1417         static set    *const_set = NULL;
1418         static ir_type *tp = NULL;
1419         struct tv_ent  key;
1420         struct tv_ent *entry;
1421         ir_node       *cnst,*symcnst;
1422         ir_graph      *rem;
1423         ir_entity     *ent = NULL;
1424
1425         if (!const_set)
1426                 const_set = new_set(cmp_tv_ent, 10);
1427         if (!tp)
1428                 tp = new_type_primitive(env->mode);
1429
1430         key.tv  = known_const;
1431         key.ent = NULL;
1432
1433         entry = set_insert(const_set, &key, sizeof(key), HASH_PTR(key.tv));
1434
1435         if (!entry->ent) {
1436                 char buf[80];
1437                 sprintf(buf, "const_%ld", get_irn_node_nr(env->irn));
1438                 ent = new_entity(get_glob_type(), new_id_from_str(buf), tp);
1439
1440                 set_entity_ld_ident(ent, get_entity_ident(ent));
1441                 set_entity_visibility(ent, ir_visibility_local);
1442                 add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
1443
1444                 /* we create a new entity here: It's initialization must resist on the
1445                     const code irg */
1446                 rem = current_ir_graph;
1447                 current_ir_graph = get_const_code_irg();
1448                 cnst = new_Const(key.tv);
1449                 current_ir_graph = rem;
1450
1451                 set_atomic_ent_value(ent, cnst);
1452
1453                 /* set the entry for hashmap */
1454                 entry->ent = ent;
1455         }                                // TODO: Wird nicht richtig in global type gesteckt, ppc32_gen_decls.c findet ihn nicht
1456
1457         symcnst = new_bd_ppc32_SymConst(env->dbg, env->block, env->mode);
1458         set_ppc32_frame_entity(symcnst, ent);
1459         return symcnst;
1460 }
1461
1462 static ir_node *gen_ppc32_SymConst(ppc32_transform_env_t *env);
1463
1464 /**
1465  * Transforms a Const.
1466  *
1467  * @param mod     the debug module
1468  * @param block   the block the new node should belong to
1469  * @param node    the ir Const node
1470  * @param mode    node mode
1471  * @return the created ppc Load immediate node
1472  */
1473 static ir_node *gen_ppc32_Const(ppc32_transform_env_t *env)
1474 {
1475         tarval *tv_const = get_ppc32_constant_tarval(env->irn);
1476         ir_node *node;
1477
1478         switch (get_nice_modecode(env->mode)){
1479                 case irm_Hu:
1480                 {
1481                         unsigned char val1 = get_tarval_sub_bits(tv_const, 1);
1482                         if (val1&0x80)
1483                         {
1484                                 ir_node *zeroreg = new_bd_ppc32_Addi_zero(env->dbg, env->block, mode_Is);
1485                                 set_ppc32_constant_tarval(zeroreg, new_tarval_from_long(0, mode_Is));
1486                                 set_ppc32_offset_mode(zeroreg, ppc32_ao_None);
1487                                 node = new_bd_ppc32_Ori(env->dbg, env->block, zeroreg, mode_Is);
1488                                 set_ppc32_offset_mode(node, ppc32_ao_Lo16);
1489                                 break;
1490                         }
1491                 }
1492                 case irm_Bu:
1493                 case irm_Bs:
1494                 case irm_Hs:
1495                         node = new_bd_ppc32_Addi_zero(env->dbg, env->block, env->mode);
1496                         set_ppc32_offset_mode(node, ppc32_ao_None);
1497                         break;
1498                 case irm_Is:
1499                 case irm_Iu:
1500                 case irm_P:
1501                 {
1502                         unsigned char val2 = get_tarval_sub_bits(tv_const,2);
1503                         unsigned char val3 = get_tarval_sub_bits(tv_const,3);
1504                         if (!val2 && !val3)
1505                         {
1506                                 unsigned char val1 = get_tarval_sub_bits(tv_const, 1);
1507                                 if (val1&0x80)
1508                                 {
1509                                         ir_node *zeroreg = new_bd_ppc32_Addi_zero(env->dbg, env->block, mode_Is);
1510                                         set_ppc32_constant_tarval(zeroreg, new_tarval_from_long(0, mode_Is));
1511                                         set_ppc32_offset_mode(zeroreg, ppc32_ao_None);
1512                                         node = new_bd_ppc32_Ori(env->dbg, env->block, zeroreg, mode_Is);
1513                                         set_ppc32_offset_mode(node, ppc32_ao_Lo16);
1514                                 }
1515                                 else
1516                                 {
1517                                         node = new_bd_ppc32_Addi_zero(env->dbg, env->block, env->mode);
1518                                         set_ppc32_offset_mode(node, ppc32_ao_None);
1519                                 }
1520                         }
1521                         else
1522                         {
1523                                 unsigned char val0 = get_tarval_sub_bits(tv_const,0);
1524                                 unsigned char val1 = get_tarval_sub_bits(tv_const,1);
1525                                 node = new_bd_ppc32_Addis_zero(env->dbg, env->block, env->mode, ppc32_ao_Hi16, tv_const, NULL);
1526                                 if (val0 || val1)
1527                                 {
1528                                         set_ppc32_constant_tarval(node, tv_const);
1529                                         node = new_bd_ppc32_Ori(env->dbg, env->block, node, env->mode);
1530                                         set_ppc32_offset_mode(node, ppc32_ao_Lo16);
1531                                 }
1532                         }
1533                         break;
1534                 }
1535
1536                 default:
1537                         panic("Mode for Const not supported: %F", env->mode);
1538         }
1539         set_ppc32_constant_tarval(node, tv_const);
1540         return node;
1541 }
1542
1543 /**
1544  * Transforms a fConst.
1545  *
1546  * @param mod     the debug module
1547  * @param block   the block the new node should belong to
1548  * @param node    the ir Const node
1549  * @param mode    node mode
1550  * @return the created ppc float Load node
1551  */
1552 static ir_node *gen_ppc32_fConst(ppc32_transform_env_t *env)
1553 {
1554         tarval *tv_const = get_ppc32_constant_tarval(env->irn);
1555
1556         switch (get_nice_modecode(env->mode)){
1557                 case irm_D:
1558                 case irm_F:
1559                 {
1560                         ir_node *addr, *load;
1561                         ir_mode *mode = env->mode;
1562                         ir_entity *ent;
1563                         env->irn = gen_fp_known_symconst(env, tv_const);
1564                         env->mode = mode_P;
1565                         ent = get_ppc32_frame_entity(env->irn);
1566 #if 0
1567                         if (is_direct_entity(ent))
1568                         {
1569                                 ident *id_symconst = get_entity_ident(ent);
1570                                 ir_node *node_addis = new_bd_ppc32_Addis_zero(env->dbg, env->block, env->mode, ppc32_ao_Ha16, NULL, id_symconst);
1571
1572                                 if (mode==mode_D)
1573                                         load = new_bd_ppc32_Lfd(env->dbg, env->block, node_addis, new_NoMem());
1574                                 else // mode_F
1575                                         load = new_bd_ppc32_Lfs(env->dbg, env->block, node_addis, new_NoMem());
1576
1577                                 set_ppc32_symconst_ident(load, id_symconst);
1578                                 set_ppc32_offset_mode(load, ppc32_ao_Lo16);
1579                         }
1580                         else
1581                         {
1582 #endif
1583                                 addr = gen_ppc32_SymConst (env);
1584                                 if (mode==mode_D)
1585                                         load = new_bd_ppc32_Lfd(env->dbg, env->block, addr, new_NoMem());
1586                                 else // mode_F
1587                                         load = new_bd_ppc32_Lfs(env->dbg, env->block, addr, new_NoMem());
1588 #if 0
1589                         }
1590 #endif
1591                         return new_rd_Proj(env->dbg, load, mode, pn_Load_res);
1592                 }
1593
1594                 default:
1595                         panic("Mode for fConst not supported: %F", env->mode);
1596         }
1597 }
1598
1599 /**
1600  * Transforms a SymConst.
1601  *
1602  * @param mod     the debug module
1603  * @param block   the block the new node should belong to
1604  * @param node    the ir Const node
1605  * @param mode    node mode
1606  * @return the created ppc Load immediate node
1607  */
1608 static ir_node *gen_ppc32_SymConst(ppc32_transform_env_t *env)
1609 {
1610         ir_entity *ent = get_ppc32_frame_entity(env->irn);
1611         ident *id_symconst = get_entity_ident(ent);
1612         ir_node *node;
1613         switch (get_nice_modecode(env->mode)){
1614                 case irm_P:
1615                 {
1616                         /*
1617                         if (is_direct_entity(ent))
1618                         {
1619                         */
1620                                 ir_node *node_addis = new_bd_ppc32_Addis_zero(env->dbg, env->block, env->mode, ppc32_ao_Hi16, NULL, id_symconst);
1621                                 node = new_bd_ppc32_Ori(env->dbg, env->block, node_addis, env->mode);
1622                                 set_ppc32_symconst_ident(node, id_symconst);
1623                                 set_ppc32_offset_mode(node, ppc32_ao_Lo16);
1624 #if 0
1625                         }
1626                         else
1627                         {
1628                                 ir_node *node_addis = new_bd_ppc32_Addis_zero(env->dbg, env->block, env->mode, ppc32_ao_Ha16, NULL, id_symconst);
1629                                 node = new_bd_ppc32_Lwz(env->dbg, env->block, node_addis, new_NoMem());
1630                                 set_ppc32_symconst_ident(node, id_symconst);
1631                                 set_ppc32_offset_mode(node, ppc32_ao_Lo16);
1632                                 node = new_rd_Proj(env->dbg, node, env->mode, pn_Load_res);
1633                         }
1634 #endif
1635                         break;
1636                 }
1637
1638                 default:
1639                         panic("Mode for SymConst not supported: %F", env->mode);
1640         }
1641         return node;
1642 }
1643
1644 /**
1645  * Transforms the given firm node (and maybe some other related nodes)
1646  * into one or more assembler nodes.
1647  *
1648  * @param node    the firm node
1649  * @param env     the debug module
1650  */
1651 void ppc32_transform_const(ir_node *node, void *env)
1652 {
1653         ppc32_code_gen_t *cgenv    = (ppc32_code_gen_t *)env;
1654         ir_node          *asm_node = NULL;
1655         ppc32_transform_env_t tenv;
1656         (void) cgenv;
1657
1658         if (is_Block(node))
1659                 return;
1660
1661         tenv.block = get_nodes_block(node);
1662         tenv.dbg   = get_irn_dbg_info(node);
1663         tenv.irg   = current_ir_graph;
1664         tenv.irn   = node;
1665         DEBUG_ONLY(tenv.mod   = cgenv->mod;)
1666         tenv.mode  = get_irn_mode(node);
1667
1668 #define OTHER_GEN(a)                        \
1669         if (get_irn_op(node) == get_op_##a()) { \
1670                 asm_node = gen_##a(&tenv);          \
1671         }
1672
1673         DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
1674
1675         OTHER_GEN(ppc32_Const)
1676         else OTHER_GEN(ppc32_fConst)
1677         else OTHER_GEN(ppc32_SymConst)
1678
1679         if (asm_node) {
1680                 exchange(node, asm_node);
1681                 DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1682         }
1683         else {
1684                 DB((tenv.mod, LEVEL_1, "ignored\n"));
1685         }
1686 #undef OTHER_GEN
1687 }