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