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