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