- remove block parameter from new_r_Proj and new_rd_Proj
[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 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 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 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                         fprintf(stderr, "Mode for Mod not supported: %s\n", get_mode_name(res_mode));
567                         assert(0);
568                         return NULL;
569
570         }
571
572         proj_div = new_rd_Proj(env->dbg, div_result, res_mode, pn_DivMod_res_div);
573
574         mul_result = new_bd_ppc32_Mullw(env->dbg, env->block, proj_div, op2, res_mode);
575         mod_result = new_bd_ppc32_Sub(env->dbg, env->block, op1, mul_result, res_mode);
576
577         exchange(proj_mod, mod_result);
578
579         return div_result;
580 }
581
582 /**
583  * Creates an ppc Shl.
584  *
585  * @param env   The transformation environment
586  * @return the created ppc Shl node
587  */
588 static ir_node *gen_Shl(ppc32_transform_env_t *env)
589 {
590         ir_node *op1 = get_Shl_left(env->irn);
591         ir_node *op2 = get_Shl_right(env->irn);
592
593         if (is_ppc32_Const(op2))
594         {
595                 ir_node *shift = new_bd_ppc32_Rlwinm(env->dbg, env->block, op1, env->mode);
596                 tarval *tv_const = get_ppc32_constant_tarval(op2);
597                 int sh = get_tarval_long(tv_const);
598                 assert(0<=sh && sh<=31);
599                 set_ppc32_rlwimi_const(shift, sh, 0, 31-sh);
600                 return shift;
601         }
602         return new_bd_ppc32_Slw(env->dbg, env->block, op1, op2, env->mode);
603 }
604
605 /**
606  * Creates an ppc Srw.
607  *
608  * @param env   The transformation environment
609  * @return the created ppc Shr node
610  */
611 static ir_node *gen_Shr(ppc32_transform_env_t *env)
612 {
613         ir_node *op1 = get_Shr_left(env->irn);
614         ir_node *op2 = get_Shr_right(env->irn);
615
616         if (is_ppc32_Const(op2))
617         {
618                 ir_node *shift = new_bd_ppc32_Rlwinm(env->dbg, env->block, op1, env->mode);
619                 tarval *tv_const = get_ppc32_constant_tarval(op2);
620                 int sh = get_tarval_long(tv_const);
621                 assert(0<=sh && sh<=31);
622                 set_ppc32_rlwimi_const(shift, 32-sh, sh, 31);
623                 return shift;
624         }
625         return new_bd_ppc32_Srw(env->dbg, env->block, op1, op2, env->mode);
626 }
627
628 /**
629  * Creates an ppc Sraw.
630  *
631  * @param env   The transformation environment
632  * @return the created ppc Sraw node
633  */
634 static ir_node *gen_Shrs(ppc32_transform_env_t *env)
635 {
636         ir_node *op1 = get_Shrs_left(env->irn);
637         ir_node *op2 = get_Shrs_right(env->irn);
638
639         if (is_ppc32_Const(op2))
640         {
641                 ir_node *shift = new_bd_ppc32_Srawi(env->dbg, env->block, op1, env->mode);
642                 tarval *tv_const = get_ppc32_constant_tarval(op2);
643                 int sh = get_tarval_long(tv_const);
644                 assert(0<=sh && sh<=31);
645                 (void) sh;
646                 set_ppc32_constant_tarval(shift, tv_const);
647                 set_ppc32_offset_mode(shift, ppc32_ao_None);
648                 return shift;
649         }
650         return new_bd_ppc32_Sraw(env->dbg, env->block, op1, op2, env->mode);
651 }
652
653 /**
654  * Creates an ppc Rotl.
655  *
656  * @param env   The transformation environment
657  * @return the created ppc Rotl node
658  */
659 static ir_node *gen_Rotl(ppc32_transform_env_t *env)
660 {
661         ir_node *op1 = get_Rotl_left(env->irn);
662         ir_node *op2 = get_Rotl_right(env->irn);
663
664         if (is_ppc32_Const(op2))
665         {
666                 ir_node *rot = new_bd_ppc32_Rlwinm(env->dbg, env->block, op1, env->mode);
667                 tarval *tv_const = get_ppc32_constant_tarval(op2);
668                 int sh = get_tarval_long(tv_const);
669                 assert(0<=sh && sh<=31);
670                 set_ppc32_rlwimi_const(rot, sh, 0, 31);
671                 return rot;
672         }
673         return new_bd_ppc32_Rlwnm(env->dbg, env->block, op1, op2, env->mode);
674 }
675
676 /**
677  * Creates an ppc Cmp.
678  *
679  * @param env   The transformation environment
680  * @return the created ppc Cmp node
681  */
682 static ir_node *gen_Cmp(ppc32_transform_env_t *env)
683 {
684         ir_node *op1 = get_Cmp_left(env->irn);
685         ir_node *op2 = get_Cmp_right(env->irn);
686
687         const ir_edge_t *edge;
688         foreach_out_edge(env->irn, edge)
689         {
690                 if (is_Proj(edge->src))
691                         set_irn_mode(edge->src, get_ppc32_mode_Cond());
692         }
693
694         if (mode_is_float(env->mode))
695                 return new_bd_ppc32_fCmpu(env->dbg, env->block, op1, op2, env->mode);
696         else if (mode_is_signed(env->mode))
697         {
698                 if (is_16bit_signed_const(op2))
699                 {
700                         ir_node *cmp = new_bd_ppc32_Cmpi(env->dbg, env->block, op1, env->mode);
701                         tarval *tv_const = get_ppc32_constant_tarval(op2);
702                         set_ppc32_constant_tarval(cmp, tv_const);
703                         set_ppc32_offset_mode(cmp, ppc32_ao_None);
704                         return cmp;
705                 }
706                 else
707                 {
708                         return new_bd_ppc32_Cmp(env->dbg, env->block, op1, op2, env->mode);
709                 }
710         }
711         else
712         {
713                 if (is_16bit_unsigned_const(op2))
714                 {
715                         ir_node *cmp = new_bd_ppc32_Cmpli(env->dbg, env->block, op1, env->mode);
716                         tarval *tv_const = get_ppc32_constant_tarval(op2);
717                         set_ppc32_constant_tarval(cmp, tv_const);
718                         set_ppc32_offset_mode(cmp, ppc32_ao_None);
719
720                         return cmp;
721                 }
722                 else
723                 {
724                         return new_bd_ppc32_Cmpl(env->dbg, env->block, op1, op2, env->mode);
725                 }
726         }
727 }
728
729 /**
730  * Transforms a Minus node.
731  *
732  * @param env   The transformation environment
733  * @return the created ppc Minus node
734  */
735 static ir_node *gen_Minus(ppc32_transform_env_t *env)
736 {
737         ir_node *op = get_Minus_op(env->irn);
738
739         switch (get_nice_modecode(env->mode)){
740                 case irm_D:
741                 case irm_F:
742                         return new_bd_ppc32_fNeg(env->dbg, env->block, op, env->mode);
743                 case irm_Is:
744                 case irm_Iu:
745                 case irm_Hs:
746                 case irm_Hu:
747                 case irm_Bs:
748                 case irm_Bu:
749                 case irm_P:
750                         return new_bd_ppc32_Neg(env->dbg, env->block, op, env->mode);
751
752                 default:
753                         panic("Mode for Neg not supported: %F", env->mode);
754         }
755 }
756
757 /**
758  * Transforms a Not node.
759  *
760  * @param env   The transformation environment
761  * @return the created ppc Not node
762  */
763 static ir_node *gen_Not(ppc32_transform_env_t *env)
764 {
765         return new_bd_ppc32_Not(env->dbg, env->block, get_Not_op(env->irn), env->mode);
766 }
767
768
769 static ir_node *own_gen_Andi_dot_lo16(ppc32_transform_env_t *env, ir_node *op, int mask)
770 {
771         ir_node *andi = new_bd_ppc32_Andi_dot(env->dbg, env->block, op, mode_T);
772         ir_node* in[1];
773         set_ppc32_offset_mode(andi, ppc32_ao_Lo16);
774         set_ppc32_constant_tarval(andi, new_tarval_from_long(mask, mode_Is));
775         in[0] = new_rd_Proj(env->dbg, andi, env->mode,1);
776         be_new_Keep(env->block, 1, in);
777         return new_rd_Proj(env->dbg, andi, env->mode,0);
778 }
779
780 /**
781  * Transforms a Conv node.
782  *
783  * @param env   The transformation environment
784  * @return the created ppc Conv node
785  */
786 static ir_node *gen_Conv(ppc32_transform_env_t *env)
787 {
788         ir_node *op = get_Conv_op(env->irn);
789         ppc32_modecode from_mode=get_nice_modecode(get_irn_mode(op));
790         ppc32_modecode to_mode=get_nice_modecode(env->mode);
791
792 #define SKIP return op
793
794         if (from_mode == to_mode) SKIP;
795
796         switch (from_mode){
797                 case irm_F:
798                         switch (to_mode)
799                         {
800                                 case irm_D: SKIP;
801                                 default:
802                                         break;
803                         }
804                         break;
805
806                 case irm_D:
807                         switch (to_mode)
808                         {
809                                 case irm_F:
810                                         return new_bd_ppc32_fRsp(env->dbg, env->block, op, env->mode);
811                                 default:
812                                         break;
813                         }
814                         break;
815
816                 case irm_Is:
817                 case irm_Iu:
818                         switch (to_mode)
819                         {
820                                 case irm_Hs:
821                                         return new_bd_ppc32_Extsh(env->dbg, env->block, op, env->mode);
822                                 case irm_Hu:
823                                         return own_gen_Andi_dot_lo16(env, op, 0xffff);
824                                 case irm_Bs:
825                                         return new_bd_ppc32_Extsb(env->dbg, env->block, op, env->mode);
826                                 case irm_Bu:
827                                         return own_gen_Andi_dot_lo16(env, op, 0xff);
828                                 case irm_Is:
829                                 case irm_Iu:
830                                         SKIP;
831                                 default:
832                                         break;
833                         }
834                         break;
835
836                 case irm_Hs:
837                 case irm_Hu:
838                         switch (to_mode)
839                         {
840                                 case irm_Iu:
841                                         if (from_mode==irm_Hu)
842                                 case irm_Hu:
843                                                 return own_gen_Andi_dot_lo16(env, op, 0xffff);
844                                 case irm_Is:
845                                         SKIP;
846                                 case irm_Bs:
847                                         return new_bd_ppc32_Extsb(env->dbg, env->block, op, env->mode);
848                                 case irm_Bu:
849                                         return own_gen_Andi_dot_lo16(env, op, 0xff);
850                                 case irm_Hs:
851                                         return new_bd_ppc32_Extsh(env->dbg, env->block, op, env->mode);
852                                 default:
853                                         break;
854                         }
855                         break;
856
857                 case irm_Bs:
858                 case irm_Bu:
859                         switch (to_mode)
860                         {
861                                 case irm_Iu:
862                                 case irm_Hu:
863                                         if (from_mode==irm_Bs)
864                                 case irm_Bu:
865                                                 return own_gen_Andi_dot_lo16(env, op, 0xff);
866                                 case irm_Is:
867                                 case irm_Hs:
868                                         SKIP;
869                                 case irm_Bs:
870                                         return new_bd_ppc32_Extsb(env->dbg, env->block, op, env->mode);
871                                 default:
872                                         break;
873                         }
874                         break;
875                 case irm_P:
876                         if (to_mode==irm_Is || to_mode==irm_Iu) SKIP;
877                         break;
878                 default:
879                         break;
880         }
881
882         panic("Mode for Conv not supported: %F -> %F", get_irn_mode(op), env->mode);
883 #undef SKIP
884 }
885
886 /**
887  * Transforms an Abs node.
888  *
889  * @param env   The transformation environment
890  * @return the ppc node generating the absolute value
891  */
892 static ir_node *gen_Abs(ppc32_transform_env_t *env)
893 {
894         ir_node *op = get_Abs_op(env->irn);
895         int shift = 7;
896         ir_node *n1,*n2;
897
898         switch (get_nice_modecode(env->mode))
899         {
900                 case irm_F:
901                 case irm_D:
902                         return new_bd_ppc32_fAbs(env->dbg, env->block, op, env->mode);
903                 case irm_Is:
904                         shift += 16;
905                 case irm_Hs:
906                         shift += 8;
907                 case irm_Bs:
908                         n1 = new_bd_ppc32_Srawi(env->dbg, env->block, op, env->mode);
909                         set_ppc32_constant_tarval(n1, new_tarval_from_long(shift, mode_Is));
910                         set_ppc32_offset_mode(n1, ppc32_ao_None);
911                         n2 = new_bd_ppc32_Add(env->dbg, env->block, op, n1, env->mode);
912                         return new_bd_ppc32_Xor(env->dbg, env->block, n2, n1, env->mode);
913                 default:
914                         break;
915         }
916         panic("Mode for Abs not supported: %F", env->mode);
917         return NULL;
918 }
919
920 /**
921  * Transforms an Cond node.
922  *
923  * @param env   The transformation environment
924  * @return a ppc branch node
925  */
926 static ir_node *gen_Cond(ppc32_transform_env_t *env)
927 {
928         ir_node *selector = get_Cond_selector(env->irn);
929         ir_mode *projmode = get_irn_mode(selector);
930         if (is_Proj(selector) && projmode==get_ppc32_mode_Cond())
931         {
932                 int projnum = get_Proj_proj(selector);
933                 ir_node *branch = new_bd_ppc32_Branch(env->dbg, env->block, selector, env->mode);
934                 set_ppc32_proj_nr(branch, projnum);
935                 return branch;
936         }
937         else
938         {
939                 ir_node *unknown_gpr = new_bd_ppc32_Unknown(env->dbg, env->block, mode_Is);
940                 ir_node *unknown_cond = new_bd_ppc32_cUnknown(env->dbg, env->block, get_ppc32_mode_Cond());
941
942                 ir_node *switch_node = new_bd_ppc32_Switch(env->dbg, env->block, selector,
943                         unknown_gpr, unknown_cond, env->mode);
944                 set_ppc32_proj_nr(switch_node, get_Cond_default_proj(env->irn));
945
946                 return switch_node;
947         }
948 }
949
950 /**
951  * Transforms an Unknown node.
952  *
953  * @param env   The transformation environment
954  * @return a ppc Unknown node
955  */
956 static ir_node *gen_Unknown(ppc32_transform_env_t *env)
957 {
958         if (mode_is_float(env->mode))
959                 return new_bd_ppc32_fUnknown(env->dbg, env->block, env->mode);
960         else if (mode_is_int(env->mode))
961                 return new_bd_ppc32_Unknown(env->dbg, env->block, env->mode);
962         else
963                 panic("Mode %F for unknown value not supported.", env->mode);
964 }
965
966 static ir_node *ldst_insert_const(ir_node *ptr, tarval **ptv, ident **pid, ppc32_transform_env_t *env)
967 {
968         tarval *tv_const = NULL;
969         ident *id_symconst = NULL;
970
971         if (is_ppc32_Const(ptr))
972         {
973                 tv_const = get_ppc32_constant_tarval(ptr);
974                 ptr = new_bd_ppc32_Addis_zero(env->dbg, env->block, mode_P, ppc32_ao_Ha16, tv_const, NULL);
975         }
976         else if (is_ppc32_SymConst(ptr))
977         {
978 #if 0
979                 ir_entity *ent = get_ppc32_frame_entity(ptr);
980                 if (is_direct_entity(ent))
981                 {
982                         id_symconst = get_entity_ident(ent);
983                         ptr = new_bd_ppc32_Addis_zero(env->dbg, env->block, mode_P, ppc32_ao_Ha16, NULL, id_symconst);
984                 }
985 #endif
986         }
987         *ptv = tv_const;
988         *pid = id_symconst;
989         return ptr;
990 }
991
992 /**
993  * Transforms a Load.
994  *
995  * @param env   The transformation environment
996  * @return the created ppc Load node
997  */
998 static ir_node *gen_Load(ppc32_transform_env_t *env)
999 {
1000         ir_node *node = env->irn;
1001         ir_node *loadptr = get_Load_ptr(node);
1002         ir_node *load;
1003         ir_mode *mode = get_Load_mode(node);
1004         tarval *tv_const = NULL;
1005         ident *id_symconst = NULL;
1006
1007         loadptr = ldst_insert_const(loadptr, &tv_const, &id_symconst, env);
1008         switch (get_nice_modecode(mode)){
1009                 case irm_Bu:
1010                         load = new_bd_ppc32_Lbz(env->dbg, env->block, loadptr, get_Load_mem(node));
1011                         break;
1012
1013                 case irm_Bs:
1014                 {
1015                         ir_node *proj_load, *extsb_node;
1016                         load =  new_bd_ppc32_Lbz(env->dbg, env->block, loadptr, get_Load_mem(node));
1017                         proj_load = new_rd_Proj(env->dbg, load, mode, pn_Load_res);
1018                         extsb_node = new_bd_ppc32_Extsb(env->dbg, env->block, proj_load, mode);
1019                         exchange(get_succ_Proj(env->irn, pn_Load_res), extsb_node);
1020                         break;
1021                 }
1022
1023
1024                 case irm_Hu:
1025                         load = new_bd_ppc32_Lhz(env->dbg, env->block, loadptr, get_Load_mem(node));
1026                         break;
1027                 case irm_Hs:
1028                         load =new_bd_ppc32_Lha(env->dbg, env->block, loadptr, get_Load_mem(node));
1029                         break;
1030                 case irm_Is:
1031                 case irm_Iu:
1032                 case irm_P:
1033                         load = new_bd_ppc32_Lwz(env->dbg, env->block, loadptr, get_Load_mem(node));
1034                         break;
1035
1036                 case irm_D:
1037                         load = new_bd_ppc32_Lfd(env->dbg, env->block, loadptr, get_Load_mem(node));
1038                         break;
1039                 case irm_F:
1040                         load = new_bd_ppc32_Lfs(env->dbg, env->block, loadptr, get_Load_mem(node));
1041                         break;
1042
1043                 default:
1044                         panic("Mode for Load not supported: %F", env->mode);
1045         }
1046
1047         if (tv_const)
1048         {
1049                 set_ppc32_offset_mode(load, ppc32_ao_Lo16);
1050                 set_ppc32_constant_tarval(load, tv_const);
1051         }
1052         else if (id_symconst)
1053         {
1054                 set_ppc32_offset_mode(load, ppc32_ao_Lo16);
1055                 set_ppc32_symconst_ident(load, id_symconst);
1056         }
1057         return load;
1058 }
1059
1060
1061
1062 /**
1063  * Transforms a Store.
1064  *
1065  * @param env   The transformation environment
1066  * @return the created ppc Store node
1067  */
1068 static ir_node *gen_Store(ppc32_transform_env_t *env)
1069 {
1070         ir_node *node = env->irn;
1071         ir_node *storeptr = get_Store_ptr(node);
1072         ir_node *valuenode = get_Store_value(node);
1073         ir_mode *mode = get_irn_mode(valuenode);
1074         ir_node *store;
1075         tarval *tv_const = NULL;
1076         ident *id_symconst = NULL;
1077
1078         storeptr = ldst_insert_const(storeptr, &tv_const, &id_symconst, env);
1079
1080         switch (get_nice_modecode(mode)){
1081                 case irm_Bu:
1082                 case irm_Bs:
1083                         store = new_bd_ppc32_Stb(env->dbg, env->block, storeptr, get_Store_value(node), get_Store_mem(node));
1084                         break;
1085
1086                 case irm_Hu:
1087                 case irm_Hs:
1088                         store = new_bd_ppc32_Sth(env->dbg, env->block, storeptr, get_Store_value(node), get_Store_mem(node));
1089                         break;
1090                 case irm_Is:
1091                 case irm_Iu:
1092                 case irm_P:
1093                         store = new_bd_ppc32_Stw(env->dbg, env->block, storeptr, get_Store_value(node), get_Store_mem(node));
1094                         break;
1095
1096                 case irm_D:
1097                         store = new_bd_ppc32_Stfd(env->dbg, env->block, storeptr, get_Store_value(node), get_Store_mem(node));
1098                         break;
1099                 case irm_F:
1100                         store = new_bd_ppc32_Stfs(env->dbg, env->block, storeptr, get_Store_value(node), get_Store_mem(node));
1101                         break;
1102
1103                 default:
1104                         panic("Mode for Store not supported: %F", env->mode);
1105         }
1106         if (tv_const)
1107         {
1108                 set_ppc32_offset_mode(store, ppc32_ao_Lo16);
1109                 set_ppc32_constant_tarval(store, tv_const);
1110         }
1111         else if (id_symconst)
1112         {
1113                 set_ppc32_offset_mode(store, ppc32_ao_Lo16);
1114                 set_ppc32_symconst_ident(store, id_symconst);
1115         }
1116         return store;
1117 }
1118
1119 /**
1120  * Transforms a CopyB.
1121  *
1122  * @param env   The transformation environment
1123  * @return the created ppc CopyB node
1124  */
1125 static ir_node *gen_CopyB(ppc32_transform_env_t *env)
1126 {
1127         ir_node *mem = get_CopyB_mem(env->irn);
1128         ir_node *src = get_CopyB_src(env->irn);
1129         ir_node *dest = get_CopyB_dst(env->irn);
1130         ir_type *type = get_CopyB_type(env->irn);
1131         int size = get_type_size_bytes(type);
1132         int offset = 0;
1133
1134         ir_node *load, *store = NULL;
1135
1136         if (size/4 >= 1)
1137         {
1138                 ir_node *res;
1139                 tarval *offset0 = new_tarval_from_long(0, mode_Is);
1140                 tarval *offset4 = new_tarval_from_long(4, mode_Is);
1141
1142                 load = new_bd_ppc32_Lwz(env->dbg, env->block, src, mem);
1143                 set_ppc32_constant_tarval(load, offset0);
1144                 set_ppc32_offset_mode(load, ppc32_ao_None);
1145                 mem = new_rd_Proj(env->dbg, load, mode_M, pn_Load_M);
1146                 res = new_rd_Proj(env->dbg, load, mode_Is, pn_Load_res);
1147
1148                 store = new_bd_ppc32_Stw(env->dbg, env->block, dest, res, mem);
1149                 set_ppc32_constant_tarval(store, offset0);
1150                 set_ppc32_offset_mode(store, ppc32_ao_None);
1151                 mem = new_rd_Proj(env->dbg, store, mode_M, pn_Store_M);
1152
1153                 if (size/4==2)
1154                 {
1155                         load = new_bd_ppc32_Lwz(env->dbg, env->block, src, mem);
1156                         set_ppc32_constant_tarval(load, offset4);
1157                         set_ppc32_offset_mode(load, ppc32_ao_None);
1158                         mem = new_rd_Proj(env->dbg, load, mode_M, pn_Load_M);
1159                         res = new_rd_Proj(env->dbg, load, mode_Is, pn_Load_res);
1160
1161                         store = new_bd_ppc32_Stw(env->dbg, env->block, dest, res, mem);
1162                         set_ppc32_constant_tarval(store, offset4);
1163                         set_ppc32_offset_mode(store, ppc32_ao_None);
1164                         mem = new_rd_Proj(env->dbg, store, mode_M, pn_Store_M);
1165
1166                         offset = 8;
1167                 }
1168                 else
1169                 {
1170                         ir_node *ornode, *mtctrnode;
1171                         ir_node* in[3];
1172                         assert(size/4-1<=0xffff);
1173                         if (size/4-1<0x8000)
1174                         {
1175                                 ornode = new_bd_ppc32_Addi_zero(env->dbg, env->block, mode_Is);
1176                                 set_ppc32_offset_mode(ornode, ppc32_ao_None);
1177                         }
1178                         else
1179                         {
1180                                 ir_node *zeroreg = new_bd_ppc32_Addi_zero(env->dbg, env->block, mode_Is);
1181                                 set_ppc32_offset_mode(zeroreg, ppc32_ao_None);
1182                                 set_ppc32_constant_tarval(zeroreg, new_tarval_from_long(0, mode_Is));
1183                                 ornode = new_bd_ppc32_Ori(env->dbg, env->block, zeroreg, mode_Is);
1184                                 set_ppc32_offset_mode(ornode, ppc32_ao_Lo16);
1185                         }
1186
1187                         set_ppc32_constant_tarval(ornode, new_tarval_from_long(size/4-1, mode_Is));
1188                         mtctrnode = new_bd_ppc32_Mtctr(env->dbg, env->block, ornode, mode_Is);
1189                         store = new_bd_ppc32_LoopCopy(env->dbg, env->block, src, dest, mtctrnode, mem, mode_T);
1190
1191                         in[0] = new_rd_Proj(env->dbg, store, mode_Is, 1); // src
1192                         in[1] = new_rd_Proj(env->dbg, store, mode_Is, 2);       // dest
1193                         in[2] = new_rd_Proj(env->dbg, store, mode_Is, 4);       // temp
1194                         be_new_Keep(env->block, 3, in);
1195                         in[0] = new_rd_Proj(env->dbg, store, mode_Is, 3); // ctr
1196                         be_new_Keep(env->block, 1, in);
1197
1198                         mem = new_rd_Proj(env->dbg, store, mode_M, 0);
1199
1200                         offset = 4;
1201                 }
1202         }
1203
1204         if (size & 2)
1205         {
1206                 ir_node *res;
1207                 tarval* offset_tarval = new_tarval_from_long(offset, mode_Is);
1208                 load = new_bd_ppc32_Lhz(env->dbg, env->block, src, mem);
1209                 set_ppc32_constant_tarval(load, offset_tarval);
1210                 set_ppc32_offset_mode(load, ppc32_ao_None);
1211                 mem = new_rd_Proj(env->dbg, load, mode_M, pn_Load_M);
1212                 res = new_rd_Proj(env->dbg, load, mode_Is, pn_Load_res);
1213
1214                 store = new_bd_ppc32_Sth(env->dbg, env->block, dest, res, mem);
1215                 set_ppc32_constant_tarval(store, offset_tarval);
1216                 set_ppc32_offset_mode(store, ppc32_ao_None);
1217                 mem = new_rd_Proj(env->dbg, store, mode_M, pn_Store_M);
1218
1219                 offset += 2;
1220         }
1221
1222         if (size & 1)
1223         {
1224                 ir_node *res;
1225                 tarval* offset_tarval = new_tarval_from_long(offset, mode_Is);
1226                 load = new_bd_ppc32_Lbz(env->dbg, env->block, src, mem);
1227                 set_ppc32_constant_tarval(load, offset_tarval);
1228                 set_ppc32_offset_mode(load, ppc32_ao_None);
1229                 mem = new_rd_Proj(env->dbg, load, mode_M, pn_Load_M);
1230                 res = new_rd_Proj(env->dbg, load, mode_Is, pn_Load_res);
1231
1232                 store = new_bd_ppc32_Stb(env->dbg, env->block, dest, res, mem);
1233                 set_ppc32_constant_tarval(store, offset_tarval);
1234                 set_ppc32_offset_mode(store, ppc32_ao_None);
1235                 // mem = new_rd_Proj(env->dbg, env->irg, store, mode_M, pn_Store_M);
1236         }
1237
1238         return store;
1239 }
1240
1241 /**
1242  * Transforms a FrameAddr into a ppc Add.
1243  *
1244  * @param env   The transformation environment
1245  */
1246 static ir_node *gen_be_FrameAddr(ppc32_transform_env_t *env)
1247 {
1248         ir_node *op = get_irn_n(env->irn, 0);
1249         ir_node *add = new_bd_ppc32_Addi(env->dbg, env->block, op, mode_P);
1250         set_ppc32_frame_entity(add, be_get_frame_entity(env->irn));
1251         return add;
1252 }
1253
1254
1255 /*********************************************************
1256  *                  _             _      _
1257  *                 (_)           | |    (_)
1258  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
1259  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
1260  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
1261  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
1262  *
1263  *********************************************************/
1264
1265 /**
1266  * the BAD transformer.
1267  */
1268 static ir_node *bad_transform(ppc32_transform_env_t *env)
1269 {
1270         panic("Transformation not implemented: %+F\n", env->irn);
1271 }
1272
1273 /**
1274  * Enters all transform functions into the generic pointer
1275  */
1276 void ppc32_register_transformers(void)
1277 {
1278         /* first clear the generic function pointer for all ops */
1279         clear_irp_opcodes_generic_func();
1280
1281 #define FIRM_OP(a)     op_##a->ops.generic = (op_func)gen_##a
1282 #define BAD(a)         op_##a->ops.generic = (op_func)bad_transform
1283 #define IGN(a)
1284
1285         FIRM_OP(Add);
1286         FIRM_OP(Mul);
1287         FIRM_OP(Mulh);
1288         FIRM_OP(And);
1289         FIRM_OP(Or);
1290         FIRM_OP(Eor);
1291
1292         FIRM_OP(Sub);
1293         FIRM_OP(Shl);
1294         FIRM_OP(Shr);
1295         FIRM_OP(Shrs);
1296         FIRM_OP(Rotl);
1297         FIRM_OP(Quot);
1298         FIRM_OP(Div);
1299         FIRM_OP(DivMod);
1300         FIRM_OP(Mod);
1301         FIRM_OP(Cmp);
1302
1303         FIRM_OP(Minus);
1304         FIRM_OP(Not);
1305         FIRM_OP(Conv);
1306         FIRM_OP(Abs);
1307
1308         FIRM_OP(Load);
1309         FIRM_OP(Store);
1310         FIRM_OP(Cond);
1311         FIRM_OP(Unknown);
1312         FIRM_OP(CopyB);
1313
1314         /* TODO: implement these nodes */
1315         BAD(Mux);
1316
1317         /* You probably don't need to handle the following nodes */
1318
1319         IGN(Call);
1320         IGN(Proj);
1321         IGN(Alloc);
1322
1323         IGN(Block);
1324         IGN(Start);
1325         IGN(End);
1326         IGN(NoMem);
1327         IGN(Phi);
1328         IGN(IJmp);
1329         IGN(Jmp);
1330         IGN(Break);
1331         IGN(Sync);
1332
1333         BAD(Raise);
1334         BAD(Sel);
1335         BAD(InstOf);
1336         BAD(Cast);
1337         BAD(Free);
1338         BAD(Tuple);
1339         BAD(Id);
1340         //BAD(Bad);
1341         BAD(Confirm);
1342         BAD(Filter);
1343         BAD(CallBegin);
1344         BAD(EndReg);
1345         BAD(EndExcept);
1346
1347         /* handle builtins */
1348         BAD(Builtin);
1349
1350         /* handle generic backend nodes */
1351         FIRM_OP(be_FrameAddr);
1352 }
1353
1354 typedef ir_node *(transform_func)(ppc32_transform_env_t *env);
1355
1356 /**
1357  * Transforms the given firm node (and maybe some other related nodes)
1358  * into one or more assembler nodes.
1359  *
1360  * @param node    the firm node
1361  * @param env     the debug module
1362  */
1363 void ppc32_transform_node(ir_node *node, void *env)
1364 {
1365         ppc32_code_gen_t *cg = (ppc32_code_gen_t *)env;
1366         ir_op *op            = get_irn_op(node);
1367         ir_node *asm_node    = NULL;
1368         (void) cg;
1369
1370         if (op == op_Block)
1371                 return;
1372
1373         DBG((cg->mod, LEVEL_1, "check %+F ... ", node));
1374
1375         if (op->ops.generic) {
1376                 ppc32_transform_env_t tenv;
1377                 transform_func *transform = (transform_func *)op->ops.generic;
1378
1379                 tenv.block    = get_nodes_block(node);
1380                 tenv.dbg      = get_irn_dbg_info(node);
1381                 tenv.irg      = current_ir_graph;
1382                 tenv.irn      = node;
1383                 tenv.mode     = get_irn_mode(node);
1384                 DEBUG_ONLY(tenv.mod = cg->mod;)
1385
1386                 asm_node = (*transform)(&tenv);
1387         }
1388
1389         if (asm_node) {
1390                 exchange(node, asm_node);
1391                 DB((cg->mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1392         }
1393         else {
1394                 DB((cg->mod, LEVEL_1, "ignored\n"));
1395         }
1396 }
1397
1398 /**
1399  * Constant generating code
1400  */
1401
1402 struct tv_ent {
1403         ir_entity *ent;
1404         tarval *tv;
1405 };
1406
1407 /** Compares two (entity, tarval) combinations */
1408 static int cmp_tv_ent(const void *a, const void *b, size_t len)
1409 {
1410         const struct tv_ent *e1 = a;
1411         const struct tv_ent *e2 = b;
1412         (void) len;
1413
1414         return !(e1->tv == e2->tv);
1415 }
1416
1417 /** Generates a SymConst node for a known FP const */
1418 static ir_node *gen_fp_known_symconst(ppc32_transform_env_t *env,
1419                                       tarval *known_const)
1420 {
1421         static set    *const_set = NULL;
1422         static ir_type *tp = NULL;
1423         struct tv_ent  key;
1424         struct tv_ent *entry;
1425         ir_node       *cnst,*symcnst;
1426         ir_graph      *rem;
1427         ir_entity     *ent = NULL;
1428
1429         if (!const_set)
1430                 const_set = new_set(cmp_tv_ent, 10);
1431         if (!tp)
1432                 tp = new_type_primitive(env->mode);
1433
1434         key.tv  = known_const;
1435         key.ent = NULL;
1436
1437         entry = set_insert(const_set, &key, sizeof(key), HASH_PTR(key.tv));
1438
1439         if (!entry->ent) {
1440                 char buf[80];
1441                 sprintf(buf, "const_%ld", get_irn_node_nr(env->irn));
1442                 ent = new_entity(get_glob_type(), new_id_from_str(buf), tp);
1443
1444                 set_entity_ld_ident(ent, get_entity_ident(ent));
1445                 set_entity_visibility(ent, ir_visibility_local);
1446                 add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
1447
1448                 /* we create a new entity here: It's initialization must resist on the
1449                     const code irg */
1450                 rem = current_ir_graph;
1451                 current_ir_graph = get_const_code_irg();
1452                 cnst = new_Const(key.tv);
1453                 current_ir_graph = rem;
1454
1455                 set_atomic_ent_value(ent, cnst);
1456
1457                 /* set the entry for hashmap */
1458                 entry->ent = ent;
1459         }                                // TODO: Wird nicht richtig in global type gesteckt, ppc32_gen_decls.c findet ihn nicht
1460
1461         symcnst = new_bd_ppc32_SymConst(env->dbg, env->block, env->mode);
1462         set_ppc32_frame_entity(symcnst, ent);
1463         return symcnst;
1464 }
1465
1466 static ir_node *gen_ppc32_SymConst(ppc32_transform_env_t *env);
1467
1468 /**
1469  * Transforms a Const.
1470  *
1471  * @param mod     the debug module
1472  * @param block   the block the new node should belong to
1473  * @param node    the ir Const node
1474  * @param mode    node mode
1475  * @return the created ppc Load immediate node
1476  */
1477 static ir_node *gen_ppc32_Const(ppc32_transform_env_t *env)
1478 {
1479         tarval *tv_const = get_ppc32_constant_tarval(env->irn);
1480         ir_node *node;
1481
1482         switch (get_nice_modecode(env->mode)){
1483                 case irm_Hu:
1484                 {
1485                         unsigned char val1 = get_tarval_sub_bits(tv_const, 1);
1486                         if (val1&0x80)
1487                         {
1488                                 ir_node *zeroreg = new_bd_ppc32_Addi_zero(env->dbg, env->block, mode_Is);
1489                                 set_ppc32_constant_tarval(zeroreg, new_tarval_from_long(0, mode_Is));
1490                                 set_ppc32_offset_mode(zeroreg, ppc32_ao_None);
1491                                 node = new_bd_ppc32_Ori(env->dbg, env->block, zeroreg, mode_Is);
1492                                 set_ppc32_offset_mode(node, ppc32_ao_Lo16);
1493                                 break;
1494                         }
1495                 }
1496                 case irm_Bu:
1497                 case irm_Bs:
1498                 case irm_Hs:
1499                         node = new_bd_ppc32_Addi_zero(env->dbg, env->block, env->mode);
1500                         set_ppc32_offset_mode(node, ppc32_ao_None);
1501                         break;
1502                 case irm_Is:
1503                 case irm_Iu:
1504                 case irm_P:
1505                 {
1506                         unsigned char val2 = get_tarval_sub_bits(tv_const,2);
1507                         unsigned char val3 = get_tarval_sub_bits(tv_const,3);
1508                         if (!val2 && !val3)
1509                         {
1510                                 unsigned char val1 = get_tarval_sub_bits(tv_const, 1);
1511                                 if (val1&0x80)
1512                                 {
1513                                         ir_node *zeroreg = new_bd_ppc32_Addi_zero(env->dbg, env->block, mode_Is);
1514                                         set_ppc32_constant_tarval(zeroreg, new_tarval_from_long(0, mode_Is));
1515                                         set_ppc32_offset_mode(zeroreg, ppc32_ao_None);
1516                                         node = new_bd_ppc32_Ori(env->dbg, env->block, zeroreg, mode_Is);
1517                                         set_ppc32_offset_mode(node, ppc32_ao_Lo16);
1518                                 }
1519                                 else
1520                                 {
1521                                         node = new_bd_ppc32_Addi_zero(env->dbg, env->block, env->mode);
1522                                         set_ppc32_offset_mode(node, ppc32_ao_None);
1523                                 }
1524                         }
1525                         else
1526                         {
1527                                 unsigned char val0 = get_tarval_sub_bits(tv_const,0);
1528                                 unsigned char val1 = get_tarval_sub_bits(tv_const,1);
1529                                 node = new_bd_ppc32_Addis_zero(env->dbg, env->block, env->mode, ppc32_ao_Hi16, tv_const, NULL);
1530                                 if (val0 || val1)
1531                                 {
1532                                         set_ppc32_constant_tarval(node, tv_const);
1533                                         node = new_bd_ppc32_Ori(env->dbg, env->block, node, env->mode);
1534                                         set_ppc32_offset_mode(node, ppc32_ao_Lo16);
1535                                 }
1536                         }
1537                         break;
1538                 }
1539
1540                 default:
1541                         panic("Mode for Const not supported: %F", env->mode);
1542         }
1543         set_ppc32_constant_tarval(node, tv_const);
1544         return node;
1545 }
1546
1547 /**
1548  * Transforms a fConst.
1549  *
1550  * @param mod     the debug module
1551  * @param block   the block the new node should belong to
1552  * @param node    the ir Const node
1553  * @param mode    node mode
1554  * @return the created ppc float Load node
1555  */
1556 static ir_node *gen_ppc32_fConst(ppc32_transform_env_t *env)
1557 {
1558         tarval *tv_const = get_ppc32_constant_tarval(env->irn);
1559
1560         switch (get_nice_modecode(env->mode)){
1561                 case irm_D:
1562                 case irm_F:
1563                 {
1564                         ir_node *addr, *load;
1565                         ir_mode *mode = env->mode;
1566                         ir_entity *ent;
1567                         env->irn = gen_fp_known_symconst(env, tv_const);
1568                         env->mode = mode_P;
1569                         ent = get_ppc32_frame_entity(env->irn);
1570 #if 0
1571                         if (is_direct_entity(ent))
1572                         {
1573                                 ident *id_symconst = get_entity_ident(ent);
1574                                 ir_node *node_addis = new_bd_ppc32_Addis_zero(env->dbg, env->block, env->mode, ppc32_ao_Ha16, NULL, id_symconst);
1575
1576                                 if (mode==mode_D)
1577                                         load = new_bd_ppc32_Lfd(env->dbg, env->block, node_addis, new_NoMem());
1578                                 else // mode_F
1579                                         load = new_bd_ppc32_Lfs(env->dbg, env->block, node_addis, new_NoMem());
1580
1581                                 set_ppc32_symconst_ident(load, id_symconst);
1582                                 set_ppc32_offset_mode(load, ppc32_ao_Lo16);
1583                         }
1584                         else
1585                         {
1586 #endif
1587                                 addr = gen_ppc32_SymConst (env);
1588                                 if (mode==mode_D)
1589                                         load = new_bd_ppc32_Lfd(env->dbg, env->block, addr, new_NoMem());
1590                                 else // mode_F
1591                                         load = new_bd_ppc32_Lfs(env->dbg, env->block, addr, new_NoMem());
1592 #if 0
1593                         }
1594 #endif
1595                         return new_rd_Proj(env->dbg, load, mode, pn_Load_res);
1596                 }
1597
1598                 default:
1599                         panic("Mode for fConst not supported: %F", env->mode);
1600         }
1601 }
1602
1603 /**
1604  * Transforms a SymConst.
1605  *
1606  * @param mod     the debug module
1607  * @param block   the block the new node should belong to
1608  * @param node    the ir Const node
1609  * @param mode    node mode
1610  * @return the created ppc Load immediate node
1611  */
1612 static ir_node *gen_ppc32_SymConst(ppc32_transform_env_t *env)
1613 {
1614         ir_entity *ent = get_ppc32_frame_entity(env->irn);
1615         ident *id_symconst = get_entity_ident(ent);
1616         ir_node *node;
1617         switch (get_nice_modecode(env->mode)){
1618                 case irm_P:
1619                 {
1620                         /*
1621                         if (is_direct_entity(ent))
1622                         {
1623                         */
1624                                 ir_node *node_addis = new_bd_ppc32_Addis_zero(env->dbg, env->block, env->mode, ppc32_ao_Hi16, NULL, id_symconst);
1625                                 node = new_bd_ppc32_Ori(env->dbg, env->block, node_addis, env->mode);
1626                                 set_ppc32_symconst_ident(node, id_symconst);
1627                                 set_ppc32_offset_mode(node, ppc32_ao_Lo16);
1628 #if 0
1629                         }
1630                         else
1631                         {
1632                                 ir_node *node_addis = new_bd_ppc32_Addis_zero(env->dbg, env->block, env->mode, ppc32_ao_Ha16, NULL, id_symconst);
1633                                 node = new_bd_ppc32_Lwz(env->dbg, env->block, node_addis, new_NoMem());
1634                                 set_ppc32_symconst_ident(node, id_symconst);
1635                                 set_ppc32_offset_mode(node, ppc32_ao_Lo16);
1636                                 node = new_rd_Proj(env->dbg, node, env->mode, pn_Load_res);
1637                         }
1638 #endif
1639                         break;
1640                 }
1641
1642                 default:
1643                         panic("Mode for SymConst not supported: %F", env->mode);
1644         }
1645         return node;
1646 }
1647
1648 /**
1649  * Transforms the given firm node (and maybe some other related nodes)
1650  * into one or more assembler nodes.
1651  *
1652  * @param node    the firm node
1653  * @param env     the debug module
1654  */
1655 void ppc32_transform_const(ir_node *node, void *env)
1656 {
1657         ppc32_code_gen_t *cgenv    = (ppc32_code_gen_t *)env;
1658         ir_node          *asm_node = NULL;
1659         ppc32_transform_env_t tenv;
1660         (void) cgenv;
1661
1662         if (is_Block(node))
1663                 return;
1664
1665         tenv.block = get_nodes_block(node);
1666         tenv.dbg   = get_irn_dbg_info(node);
1667         tenv.irg   = current_ir_graph;
1668         tenv.irn   = node;
1669         DEBUG_ONLY(tenv.mod   = cgenv->mod;)
1670         tenv.mode  = get_irn_mode(node);
1671
1672 #define OTHER_GEN(a)                        \
1673         if (get_irn_op(node) == get_op_##a()) { \
1674                 asm_node = gen_##a(&tenv);          \
1675         }
1676
1677         DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
1678
1679         OTHER_GEN(ppc32_Const)
1680         else OTHER_GEN(ppc32_fConst)
1681         else OTHER_GEN(ppc32_SymConst)
1682
1683         if (asm_node) {
1684                 exchange(node, asm_node);
1685                 DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1686         }
1687         else {
1688                 DB((tenv.mod, LEVEL_1, "ignored\n"));
1689         }
1690 #undef OTHER_GEN
1691 }