Remove the unused parameter const arch_env_t *env from arch_set_irn_register().
[libfirm] / ir / be / mips / mips_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 codegenrator (transform FIRM into mips FIRM
23  * @author  Matthias Braun, Mehdi
24  * @version $Id$
25  */
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <limits.h>
31
32 #include "irnode_t.h"
33 #include "irgraph_t.h"
34 #include "irmode_t.h"
35 #include "irgmod.h"
36 #include "iredges.h"
37 #include "irvrfy.h"
38 #include "ircons.h"
39 #include "irprintf.h"
40 #include "irop.h"
41 #include "iropt_t.h"
42 #include "debug.h"
43 #include "error.h"
44
45 #include "../benode_t.h"
46 #include "../beabi.h"
47 #include "../besched.h"
48 #include "../besched_t.h"
49 #include "../beirg_t.h"
50 #include "../betranshlp.h"
51 #include "bearch_mips_t.h"
52
53 #include "mips_nodes_attr.h"
54 #include "archop.h"
55 #include "mips_transform.h"
56 #include "mips_new_nodes.h"
57 #include "mips_map_regs.h"
58 #include "mips_util.h"
59 #include "mips_emitter.h"
60
61 #include "gen_mips_regalloc_if.h"
62
63 /****************************************************************************************************
64  *                  _        _                        __                           _   _
65  *                 | |      | |                      / _|                         | | (_)
66  *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
67  * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
68  * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
69  * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
70  *
71  ****************************************************************************************************/
72
73 typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg,
74         ir_node *block, ir_node *left, ir_node *right);
75
76 static INLINE int mode_needs_gp_reg(ir_mode *mode) {
77         return mode_is_int(mode) || mode_is_reference(mode);
78 }
79
80 ir_node *mips_create_Immediate(long val)
81 {
82         ir_graph *irg   = current_ir_graph;
83         ir_node  *block = get_irg_start_block(irg);
84         const arch_register_t **slots;
85         ir_node  *res;
86
87         assert(val >=  -32768 && val <= 32767);
88         res      = new_rd_mips_Immediate(NULL, irg, block, MIPS_IMM_CONST, NULL,
89                                          val);
90         slots    = get_mips_slots(res);
91         slots[0] = &mips_gp_regs[REG_GP_NOREG];
92
93         return res;
94 }
95
96 ir_node* mips_create_zero(void)
97 {
98         ir_graph *irg   = current_ir_graph;
99         ir_node  *block = get_irg_start_block(irg);
100         ir_node  *zero  = new_rd_mips_zero(NULL, irg, block);
101         const arch_register_t **slots = get_mips_slots(zero);
102
103         slots[0] = &mips_gp_regs[REG_ZERO];
104
105         return zero;
106 }
107
108 static ir_node *try_create_Immediate(ir_node *node)
109 {
110         tarval   *tv;
111         long      val;
112         ir_mode  *mode;
113
114         if(!is_Const(node))
115                 return NULL;
116
117         mode = get_irn_mode(node);
118         if(!mode_needs_gp_reg(mode))
119                 return NULL;
120
121         tv = get_Const_tarval(node);
122         if(tarval_is_long(tv)) {
123                 val = get_tarval_long(tv);
124         } else {
125                 ir_fprintf(stderr, "Optimisation Warning: tarval %+F is not a long?\n",
126                            node);
127                 return NULL;
128         }
129
130         if(val < -32768 || val > 32767)
131                 return NULL;
132
133         return mips_create_Immediate(val);
134 }
135
136 static void create_binop_operands(ir_node **new_left, ir_node **new_right,
137                                   ir_node *left, ir_node *right,
138                                   int is_commutative)
139 {
140         *new_right = try_create_Immediate(right);
141         if(*new_right != NULL) {
142                 *new_left = be_transform_node(left);
143                 return;
144         }
145         if(is_commutative) {
146                 *new_right = try_create_Immediate(left);
147                 if(*new_right != NULL) {
148                         *new_left = be_transform_node(right);
149                         return;
150                 }
151         }
152
153         *new_left  = be_transform_node(left);
154         *new_right = be_transform_node(right);
155 }
156
157 static ir_node *gen_binop(ir_node *node, ir_node *left, ir_node *right,
158                           construct_binop_func func, int supports_immediate)
159 {
160         ir_graph *irg   = current_ir_graph;
161         dbg_info *dbgi  = get_irn_dbg_info(node);
162         ir_node  *block = be_transform_node(get_nodes_block(node));
163         ir_node  *res;
164         ir_node  *new_left, *new_right;
165
166         assert(mode_needs_gp_reg(get_irn_mode(node)));
167
168         if(supports_immediate) {
169                 int is_commutative = is_op_commutative(get_irn_op(node));
170                 create_binop_operands(&new_left, &new_right, left, right,
171                                       is_commutative);
172         } else {
173                 new_left  = be_transform_node(left);
174                 new_right = be_transform_node(right);
175         }
176
177         res = func(dbgi, irg, block, new_left, new_right);
178
179         return res;
180 }
181
182 static ir_node *gen_Add(ir_node *node)
183 {
184         /* TODO: match add(symconst, const) */
185         return gen_binop(node, get_Add_left(node), get_Add_right(node),
186                          new_rd_mips_addu, 1);
187 }
188
189 static ir_node *gen_Sub(ir_node *node)
190 {
191         return gen_binop(node, get_Sub_left(node), get_Sub_right(node),
192                          new_rd_mips_addu, 0);
193 }
194
195 static ir_node *gen_And(ir_node *node)
196 {
197         return gen_binop(node, get_Add_left(node), get_Add_right(node),
198                          new_rd_mips_and, 1);
199 }
200
201 static ir_node *gen_Or(ir_node *node)
202 {
203         return gen_binop(node, get_Add_left(node), get_Add_right(node),
204                          new_rd_mips_or, 1);
205 }
206
207 static ir_node *gen_Eor(ir_node *node)
208 {
209         return gen_binop(node, get_Add_left(node), get_Add_right(node),
210                          new_rd_mips_xor, 1);
211 }
212
213 static ir_node *gen_Shl(ir_node *node)
214 {
215         return gen_binop(node, get_Add_left(node), get_Add_right(node),
216                          new_rd_mips_sll, 1);
217 }
218
219 static ir_node *gen_Shr(ir_node *node)
220 {
221         return gen_binop(node, get_Add_left(node), get_Add_right(node),
222                          new_rd_mips_srl, 1);
223 }
224
225 static ir_node *gen_Shrs(ir_node *node)
226 {
227         return gen_binop(node, get_Add_left(node), get_Add_right(node),
228                          new_rd_mips_sra, 1);
229 }
230
231 static ir_node *gen_Not(ir_node *node)
232 {
233         ir_graph *irg   = current_ir_graph;
234         dbg_info *dbgi  = get_irn_dbg_info(node);
235         ir_node  *block = be_transform_node(get_nodes_block(node));
236         ir_node  *op    = get_Not_op(node);
237         ir_node  *new_op;
238         ir_node  *res;
239         ir_node  *one;
240
241         /* we can transform not->or to nor */
242         if(is_Or(op)) {
243                 return gen_binop(op, get_Or_left(op), get_Or_right(op),
244                                  new_rd_mips_nor, 1);
245         }
246
247         /* construct (op < 1) */
248         one    = mips_create_Immediate(1);
249         new_op = be_transform_node(op);
250         res    = new_rd_mips_sltu(dbgi, irg, block, new_op, one);
251
252         return res;
253 }
254
255 static ir_node *gen_Minus(ir_node *node)
256 {
257         ir_graph *irg    = current_ir_graph;
258         dbg_info *dbgi   = get_irn_dbg_info(node);
259         ir_node  *block  = be_transform_node(get_nodes_block(node));
260         ir_node  *op     = get_Minus_op(node);
261         ir_node  *new_op = be_transform_node(op);
262         ir_node  *res;
263         ir_node  *zero;
264
265         /* construct (0 - op) */
266         zero = mips_create_zero();
267         res  = new_rd_mips_subu(dbgi, irg, block, zero, new_op);
268
269         return res;
270 }
271
272 static ir_node *gen_Abs(ir_node *node)
273 {
274         ir_graph *irg    = current_ir_graph;
275         dbg_info *dbgi   = get_irn_dbg_info(node);
276         ir_node  *block  = be_transform_node(get_nodes_block(node));
277         ir_node  *op     = get_Abs_op(node);
278         ir_node  *new_op = be_transform_node(op);
279         ir_node  *sra_const, *sra, *add, *xor;
280
281         /* TODO: support other bit sizes... */
282         assert(get_mode_size_bits(get_irn_mode(node)) == 32);
283         sra_const = mips_create_Immediate(31);
284         sra       = new_rd_mips_sra(dbgi, irg, block, new_op, sra_const);
285         add       = new_rd_mips_addu(dbgi, irg, block, new_op, sra);
286         xor       = new_rd_mips_xor(dbgi, irg, block, sra, add);
287
288         return xor;
289 }
290
291 static ir_node* gen_Const(ir_node *node)
292 {
293         ir_graph *irg   = current_ir_graph;
294         dbg_info *dbgi  = get_irn_dbg_info(node);
295         ir_node  *block = be_transform_node(get_nodes_block(node));
296         tarval   *tv    = get_Const_tarval(node);
297         ir_node  *upper_node;
298         ir_node  *lower_node;
299         ir_node  *or_const;
300         unsigned long val, lower, upper;
301
302         if(tarval_is_long(tv)) {
303                 val = get_tarval_long(tv);
304         } else {
305                 panic("Can't get value of tarval %+F", node);
306         }
307
308         val = get_tarval_long(tv);
309
310         lower = val & 0xffff;
311         upper = (val >> 16) & 0xffff;
312         if(upper == 0) {
313                 upper_node = mips_create_zero();
314         } else {
315                 upper_node = new_rd_mips_lui(dbgi, irg, block, MIPS_IMM_CONST, NULL,
316                                              upper);
317         }
318
319         if(lower == 0)
320                 return upper_node;
321
322         or_const   = mips_create_Immediate(lower);
323         lower_node = new_rd_mips_or(dbgi, irg, block, upper_node, or_const);
324
325         return lower_node;
326 }
327
328 static ir_node* gen_SymConst(ir_node *node)
329 {
330         ir_graph *irg   = current_ir_graph;
331         dbg_info *dbgi  = get_irn_dbg_info(node);
332         ir_node  *block = be_transform_node(get_nodes_block(node));
333         ir_entity *entity;
334         const arch_register_t **slots;
335         ir_node *lui, *or_const, *or;
336
337         if(get_SymConst_kind(node) != symconst_addr_ent) {
338                 panic("Only address entity symconsts supported in mips backend");
339         }
340
341         entity = get_SymConst_entity(node);
342
343         lui            = new_rd_mips_lui(dbgi, irg, block, MIPS_IMM_SYMCONST_HI,
344                                          entity, 0);
345         or_const       = new_rd_mips_Immediate(dbgi, irg, block,
346                                                MIPS_IMM_SYMCONST_LO, entity, 0);
347         or             = new_rd_mips_or(dbgi, irg, block, lui, or_const);
348
349         slots    = get_mips_slots(or_const);
350         slots[0] = &mips_gp_regs[REG_GP_NOREG];
351
352         return or;
353 }
354
355 typedef ir_node* (*gen_load_func) (dbg_info *dbg, ir_graph *irg,
356                                    ir_node *block, ir_node *ptr, ir_node *mem,
357                                    ir_entity *entity, long offset);
358
359 /**
360  * Generates a mips node for a firm Load node
361  */
362 static ir_node *gen_Load(ir_node *node)
363 {
364         ir_graph *irg     = current_ir_graph;
365         dbg_info *dbgi    = get_irn_dbg_info(node);
366         ir_node  *block   = be_transform_node(get_nodes_block(node));
367         ir_node  *mem     = get_Load_mem(node);
368         ir_node  *new_mem = be_transform_node(mem);
369         ir_node  *ptr     = get_Load_ptr(node);
370         ir_node  *new_ptr = be_transform_node(ptr);
371         ir_mode  *mode    = get_Load_mode(node);
372         int       sign    = get_mode_sign(mode);
373         ir_node  *res;
374         gen_load_func func;
375
376         ASSERT_NO_FLOAT(mode);
377         assert(mode_needs_gp_reg(mode));
378
379         /* TODO: make use of offset in ptrs */
380
381         switch(get_mode_size_bits(mode)) {
382         case 32:
383                 func = new_rd_mips_lw;
384                 break;
385         case 16:
386                 func = sign ? new_rd_mips_lh : new_rd_mips_lhu;
387                 break;
388         case 8:
389                 func = sign ? new_rd_mips_lb : new_rd_mips_lbu;
390                 break;
391         default:
392                 panic("mips backend only support 32, 16, 8 bit loads");
393         }
394
395         res = func(dbgi, irg, block, new_ptr, new_mem, NULL, 0);
396         set_irn_pinned(res, get_irn_pinned(node));
397
398         return res;
399 }
400
401 typedef ir_node* (*gen_store_func) (dbg_info *dbg, ir_graph *irg,
402                                     ir_node *block, ir_node *ptr, ir_node *val,
403                                     ir_node *mem, ir_entity *ent, long offset);
404
405 /**
406  * Generates a mips node for a firm Store node
407  */
408 static ir_node *gen_Store(ir_node *node)
409 {
410         ir_graph    *irg     = current_ir_graph;
411         dbg_info    *dbgi    = get_irn_dbg_info(node);
412         ir_node     *block   = be_transform_node(get_nodes_block(node));
413         ir_node     *mem     = get_Store_mem(node);
414         ir_node     *new_mem = be_transform_node(mem);
415         ir_node     *ptr     = get_Store_ptr(node);
416         ir_node     *new_ptr = be_transform_node(ptr);
417         ir_node     *val     = get_Store_value(node);
418         ir_node     *new_val = be_transform_node(val);
419         ir_mode     *mode    = get_irn_mode(val);
420         gen_store_func func;
421         ir_node     *res;
422
423         assert(mode_needs_gp_reg(mode));
424
425         switch(get_mode_size_bits(mode)) {
426         case 32:
427                 func = new_rd_mips_sw;
428                 break;
429         case 16:
430                 func = new_rd_mips_sh;
431                 break;
432         case 8:
433                 func = new_rd_mips_sb;
434                 break;
435         default:
436                 panic("store only supported for 32, 16, 8 bit values in mips backend");
437         }
438
439         res = func(dbgi, irg, block, new_ptr, new_val, new_mem, NULL, 0);
440         set_irn_pinned(res, get_irn_pinned(node));
441
442         return res;
443 }
444
445 static ir_node *gen_Proj_DivMod(ir_node *node)
446 {
447         ir_graph *irg     = current_ir_graph;
448         dbg_info *dbgi    = get_irn_dbg_info(node);
449         ir_node  *block   = be_transform_node(get_nodes_block(node));
450         ir_node  *divmod  = get_Proj_pred(node);
451         ir_node  *new_div = be_transform_node(divmod);
452         long      pn      = get_Proj_proj(node);
453         ir_node  *proj;
454
455         assert(is_mips_div(new_div) || is_mips_divu(new_div));
456
457         switch(get_irn_opcode(divmod)) {
458         case iro_Div:
459                 switch(pn) {
460                 case pn_Div_M:
461                         return new_rd_Proj(dbgi, irg, block, new_div, mode_M,
462                                            pn_mips_div_M);
463                 case pn_Div_res:
464                         proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
465                                            pn_mips_div_lohi);
466                         return new_rd_mips_mflo(dbgi, irg, block, proj);
467                 default:
468                         break;
469                 }
470         case iro_Mod:
471                 switch(pn) {
472                 case pn_Mod_M:
473                         return new_rd_Proj(dbgi, irg, block, new_div, mode_M,
474                                            pn_mips_div_M);
475                 case pn_Mod_res:
476                         proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
477                                            pn_mips_div_lohi);
478                         return new_rd_mips_mfhi(dbgi, irg, block, proj);
479                 default:
480                         break;
481                 }
482
483         case iro_DivMod:
484                 switch(pn) {
485                 case pn_Div_M:
486                         return new_rd_Proj(dbgi, irg, block, new_div, mode_M,
487                                            pn_mips_div_M);
488                 case pn_DivMod_res_div:
489                         proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
490                                            pn_mips_div_lohi);
491                         return new_rd_mips_mflo(dbgi, irg, block, proj);
492                 case pn_DivMod_res_mod:
493                         proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
494                                            pn_mips_div_lohi);
495                         return new_rd_mips_mfhi(dbgi, irg, block, proj);
496                 default:
497                         break;
498                 }
499         default:
500                 break;
501         }
502
503         panic("invalid proj attached to %+F", divmod);
504 }
505
506 static ir_node *gen_Proj_Start(ir_node *node)
507 {
508         ir_graph *irg   = current_ir_graph;
509         dbg_info *dbgi  = get_irn_dbg_info(node);
510         ir_node  *block = be_transform_node(get_nodes_block(node));
511         long      pn    = get_Proj_proj(node);
512
513         if(pn == pn_Start_X_initial_exec) {
514                 /* we exchange the projx with a jump */
515                 ir_node *jump = new_rd_Jmp(dbgi, irg, block);
516                 return jump;
517         }
518         if(node == get_irg_anchor(irg, anchor_tls)) {
519                 /* TODO... */
520                 return be_duplicate_node(node);
521         }
522         return be_duplicate_node(node);
523 }
524
525 static ir_node *gen_Proj(ir_node *node)
526 {
527         ir_graph *irg  = current_ir_graph;
528         dbg_info *dbgi = get_irn_dbg_info(node);
529         ir_node  *pred = get_Proj_pred(node);
530
531         switch(get_irn_opcode(pred)) {
532         case iro_Load:
533                 break;
534         case iro_Store:
535                 break;
536         case iro_Div:
537         case iro_Mod:
538         case iro_DivMod:
539                 return gen_Proj_DivMod(node);
540
541         case iro_Start:
542                 return gen_Proj_Start(node);
543
544         default:
545                 assert(get_irn_mode(node) != mode_T);
546                 if(mode_needs_gp_reg(get_irn_mode(node))) {
547                         ir_node *new_pred = be_transform_node(pred);
548                         ir_node *block    = be_transform_node(get_nodes_block(node));
549                         long     pn       = get_Proj_proj(node);
550
551                         return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn);
552                 }
553                 break;
554         }
555
556         return be_duplicate_node(node);
557 }
558
559 static ir_node *gen_Phi(ir_node *node)
560 {
561         ir_graph *irg   = current_ir_graph;
562         dbg_info *dbgi  = get_irn_dbg_info(node);
563         ir_node  *block = be_transform_node(get_nodes_block(node));
564         ir_mode  *mode  = get_irn_mode(node);
565         ir_node  *phi;
566
567         if(mode_needs_gp_reg(mode)) {
568                 assert(get_mode_size_bits(mode) <= 32);
569                 mode = mode_Iu;
570         }
571
572         /* phi nodes allow loops, so we use the old arguments for now
573          * and fix this later */
574         phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node),
575                           get_irn_in(node) + 1);
576         copy_node_attr(node, phi);
577         be_duplicate_deps(node, phi);
578
579         be_enqueue_preds(node);
580
581         return phi;
582 }
583
584 #if 0
585 static
586 ir_node *gen_node_for_SwitchCond(mips_transform_env_t *env)
587 {
588         ir_node *selector = get_Cond_selector(env->irn);
589         ir_mode *selector_mode = get_irn_mode(selector);
590         ir_node *node = env->irn;
591         dbg_info *dbg = env->dbg;
592         ir_graph *irg = env->irg;
593         ir_node *block = env->block;
594         ir_node *sub, *sltu, *minval_const, *max_const, *switchjmp;
595         ir_node *defaultproj, *defaultproj_succ;
596         ir_node *beq, *sl;
597         long pn, minval, maxval, defaultprojn;
598         const ir_edge_t *edge;
599         ir_node *zero, *two_const, *add, *la, *load, *proj;
600         ir_mode *unsigned_mode;
601         mips_attr_t *attr;
602
603         // mode_b conds are handled by gen_node_for_Proj
604         if(get_mode_sort(selector_mode) != irms_int_number)
605                 return env->irn;
606
607         assert(get_mode_size_bits(selector_mode) == 32);
608
609         defaultproj = NULL;
610         defaultprojn = get_Cond_defaultProj(node);
611
612         // go over all projs to find min-&maxval of the switch
613         minval = INT_MAX;
614         maxval = INT_MIN;
615         foreach_out_edge(node, edge) {
616                 ir_node* proj = get_edge_src_irn(edge);
617                 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
618
619                 pn = get_Proj_proj(proj);
620                 if(pn == defaultprojn) {
621                         defaultproj = proj;
622                         continue;
623                 }
624
625                 if(pn < minval)
626                         minval = pn;
627                 if(pn > maxval)
628                         maxval = pn;
629         }
630         assert(defaultproj != NULL);
631
632         // subtract minval from the switch value
633
634         if(minval != 0) {
635                 minval_const = new_rd_Const(dbg, irg, block, selector_mode, new_tarval_from_long(minval, selector_mode));
636                 minval_const = gen_node_for_Const(env, dbg, irg, block, minval_const);
637                 sub = new_rd_mips_sub(dbg, irg, block, selector, minval_const);
638         } else {
639                 sub = selector;
640         }
641
642         // compare if we're above maxval-minval or below zero.
643         // we can do this with 1 compare because we use unsigned mode
644         unsigned_mode = new_ir_mode(get_mode_name(selector_mode),
645                         get_mode_sort(selector_mode), get_mode_size_bits(selector_mode),
646                         0, get_mode_arithmetic(selector_mode), get_mode_modulo_shift(selector_mode));
647
648         max_const = new_rd_Const(dbg, irg, block, unsigned_mode, new_tarval_from_long(maxval - minval + 1, unsigned_mode));
649         max_const = gen_node_for_Const(env, dbg, irg, block, max_const);
650         sltu = new_rd_mips_slt(dbg, irg, block, sub, max_const);
651
652         zero = gen_zero_node(env, dbg, irg, block);
653         beq = new_rd_mips_beq(dbg, irg, block, sltu, zero, mode_T);
654
655         // attach defaultproj to beq now
656         set_irn_n(defaultproj, 0, beq);
657         set_Proj_proj(defaultproj, 1);
658
659         two_const = new_rd_Const(dbg, irg, block, unsigned_mode, new_tarval_from_long(2, unsigned_mode));
660         two_const = gen_node_for_Const(env, dbg, irg, block, two_const);
661         sl = new_rd_mips_sl(dbg, irg, block, sub, two_const);
662
663         la = new_rd_mips_la(dbg, irg, block);
664         add = new_rd_mips_addu(dbg, irg, block, sl, la);
665         load = new_rd_mips_load_r(dbg, irg, block, new_rd_NoMem(irg), add, mode_T);
666         attr = get_mips_attr(load);
667         attr->modes.load_store_mode = mode_Iu;
668         attr->tv = new_tarval_from_long(0, mode_Iu);
669
670         proj = new_rd_Proj(dbg, irg, block, load, mode_Iu, pn_Load_res);
671
672         switchjmp = new_rd_mips_SwitchJump(dbg, irg, block, proj, mode_T);
673         attr = get_mips_attr(switchjmp);
674         attr->switch_default_pn = defaultprojn;
675
676         edge = get_irn_out_edge_first(defaultproj);
677         defaultproj_succ = get_edge_src_irn(edge);
678         attr->symconst_id = new_id_from_str(mips_get_block_label(defaultproj_succ));
679
680         attr = get_mips_attr(la);
681         attr->symconst_id = new_id_from_str(mips_get_jumptbl_label(switchjmp));
682
683         return switchjmp;
684 }
685 #endif
686
687 static ir_node *gen_Cond(ir_node *node)
688 {
689         ir_graph *irg       = current_ir_graph;
690         dbg_info *dbgi      = get_irn_dbg_info(node);
691         ir_node  *block     = get_nodes_block(node);
692         ir_node  *sel_proj  = get_Cond_selector(node);
693         ir_node  *cmp       = get_Proj_pred(sel_proj);
694         ir_node  *left      = get_Cmp_left(cmp);
695         ir_node  *new_left  = be_transform_node(left);
696         ir_node  *right     = get_Cmp_right(cmp);
697         ir_node  *new_right = be_transform_node(right);
698         long      pnc       = get_Proj_proj(sel_proj);
699         ir_node  *res;
700         ir_node  *slt;
701         ir_node  *zero;
702
703         /* TODO: use blez & co. when possible */
704
705         switch(pnc) {
706         case pn_Cmp_False:
707         case pn_Cmp_True:
708         case pn_Cmp_Leg:
709                 panic("mips backend can't handle unoptimized constant Cond");
710
711         case pn_Cmp_Eq:
712                 res = new_rd_mips_beq(dbgi, irg, block, new_left, new_right);
713                 break;
714
715         case pn_Cmp_Lt:
716                 zero = mips_create_zero();
717                 slt  = new_rd_mips_slt(dbgi, irg, block, new_left, new_right);
718                 res  = new_rd_mips_bne(dbgi, irg, block, slt, zero);
719                 break;
720
721         case pn_Cmp_Le:
722                 zero = mips_create_zero();
723                 slt  = new_rd_mips_slt(dbgi, irg, block, new_right, new_left);
724                 res  = new_rd_mips_beq(dbgi, irg, block, slt, zero);
725                 break;
726
727         case pn_Cmp_Gt:
728                 zero = mips_create_zero();
729                 slt  = new_rd_mips_slt(dbgi, irg, block, new_right, new_left);
730                 res  = new_rd_mips_bne(dbgi, irg, block, slt, zero);
731                 break;
732
733         case pn_Cmp_Ge:
734                 zero = mips_create_zero();
735                 slt  = new_rd_mips_slt(dbgi, irg, block, new_right, new_left);
736                 res  = new_rd_mips_bne(dbgi, irg, block, slt, zero);
737                 break;
738
739         case pn_Cmp_Lg:
740                 res = new_rd_mips_bne(dbgi, irg, block, new_left, new_right);
741                 break;
742
743         default:
744                 panic("mips backend doesn't handle unordered compares yet");
745         }
746
747         return res;
748 }
749
750 static ir_node *gen_Conv(ir_node *node)
751 {
752         ir_graph *irg      = current_ir_graph;
753         dbg_info *dbgi     = get_irn_dbg_info(node);
754         ir_node  *block    = be_transform_node(get_nodes_block(node));
755         ir_node  *op       = get_Conv_op(node);
756         ir_node  *new_op   = be_transform_node(op);
757         ir_mode  *src_mode = get_irn_mode(op);
758         ir_mode  *dst_mode = get_irn_mode(node);
759         int       src_size = get_mode_size_bits(src_mode);
760         int       dst_size = get_mode_size_bits(dst_mode);
761         ir_node  *res;
762
763         assert(mode_needs_gp_reg(src_mode));
764         assert(mode_needs_gp_reg(dst_mode));
765
766         /* we only need to do something on upconvs */
767         if(src_size >= dst_size) {
768                 /* unnecessary conv */
769                 return new_op;
770         }
771
772         if(mode_is_signed(src_mode)) {
773                 if(src_size == 8) {
774                         res = new_rd_mips_seb(dbgi, irg, block, new_op);
775                 } else if(src_size == 16) {
776                         res = new_rd_mips_seh(dbgi, irg, block, new_op);
777                 } else {
778                         panic("invalid conv %+F", node);
779                 }
780         } else {
781                 ir_node *and_const;
782
783                 if(src_size == 8) {
784                         and_const = mips_create_Immediate(0xff);
785                 } else if(src_size == 16) {
786                         and_const = mips_create_Immediate(0xffff);
787                 } else {
788                         panic("invalid conv %+F", node);
789                 }
790                 res = new_rd_mips_and(dbgi, irg, block, new_op, and_const);
791         }
792
793         return res;
794 }
795
796 static ir_node *create_div(ir_node *node, ir_node *left, ir_node *right,
797                            ir_mode *mode)
798 {
799         ir_graph *irg       = current_ir_graph;
800         dbg_info *dbgi      = get_irn_dbg_info(node);
801         ir_node  *block     = be_transform_node(get_nodes_block(node));
802         ir_node  *new_left  = be_transform_node(left);
803         ir_node  *new_right = be_transform_node(right);
804         ir_node  *res;
805
806         if(mode_is_signed(mode)) {
807                 res = new_rd_mips_div(dbgi, irg, block, new_left, new_right);
808         } else {
809                 res = new_rd_mips_divu(dbgi, irg, block, new_left, new_right);
810         }
811
812         set_irn_pinned(res, get_irn_pinned(node));
813
814         return res;
815 }
816
817 static ir_node *gen_DivMod(ir_node *node)
818 {
819         return create_div(node, get_DivMod_left(node), get_DivMod_right(node),
820                           get_DivMod_resmode(node));
821 }
822
823 static ir_node *gen_Div(ir_node *node)
824 {
825         return create_div(node, get_Div_left(node), get_Div_right(node),
826                           get_Div_resmode(node));
827 }
828
829 static ir_node *gen_Mod(ir_node *node)
830 {
831         return create_div(node, get_Mod_left(node), get_Mod_right(node),
832                           get_Mod_resmode(node));
833 }
834
835 #if 0
836 static ir_node *gen_node_for_Mul(mips_transform_env_t *env) {
837         ir_node *node = env->irn;
838         ir_node *mul;
839         ir_node *mflo;
840         ir_node *op1, *op2;
841         ir_mode *mode = get_irn_mode(node);
842
843         op1 = get_Mul_left(node);
844         op2 = get_Mul_right(node);
845
846         assert(get_mode_size_bits(env->mode) == 32);
847         assert(get_mode_size_bits(get_irn_mode(op1)) == get_mode_size_bits(env->mode));
848         assert(get_mode_size_bits(get_irn_mode(op2)) == get_mode_size_bits(env->mode));
849
850         if(mode_is_signed(mode)) {
851                 mul = new_rd_mips_mult(env->dbg, env->irg, env->block, get_Mul_left(node), get_Mul_right(node));
852         } else {
853                 mul = new_rd_mips_multu(env->dbg, env->irg, env->block, get_Mul_left(node), get_Mul_right(node));
854         }
855         mflo = new_rd_mips_mflo(env->dbg, env->irg, env->block, mul);
856
857         return mflo;
858 }
859
860 static
861 ir_node *gen_node_for_IJmp(mips_transform_env_t *env) {
862         ir_graph *irg    = env->irg;
863         ir_node  *node   = env->irn;
864         dbg_info *dbg    = get_irn_dbg_info(node);
865         ir_node  *block  = get_nodes_block(node);
866         ir_node  *target = get_IJmp_target(node);
867
868         return new_rd_mips_jr(dbg, irg, block, target);
869 }
870
871 static
872 ir_node *gen_node_for_Rot(mips_transform_env_t *env) {
873         ir_node *node = env->irn;
874         ir_node *subu, *srlv, *sllv, *or;
875
876         subu = new_rd_mips_subuzero(env->dbg, env->irg, env->block, get_Rot_right(node));
877         srlv = new_rd_mips_srlv(env->dbg, env->irg, env->block, get_Rot_left(node), subu);
878         sllv = new_rd_mips_sllv(env->dbg, env->irg, env->block, get_Rot_left(node), get_Rot_right(node));
879         or = new_rd_mips_or(env->dbg, env->irg, env->block, sllv, srlv);
880
881         return or;
882 }
883 #endif
884
885 static ir_node *gen_Unknown(ir_node *node)
886 {
887         (void) node;
888         assert(mode_needs_gp_reg(get_irn_mode(node)));
889         return mips_create_zero();
890 }
891
892 #if 0
893 /*
894  * lower a copyB into standard Firm assembler :-)
895  */
896 ir_node *gen_code_for_CopyB(ir_node *block, ir_node *node) {
897         ir_node *cnt, *sub;
898         ir_node *dst = get_CopyB_dst(node);
899         ir_node *src = get_CopyB_src(node);
900         ir_type *type = get_CopyB_type(node);
901         ir_node *mem = get_CopyB_mem(node);
902         ir_node *mm[4];
903         ir_node *result = NULL;
904         int size = get_type_size_bytes(type);
905         dbg_info *dbg = get_irn_dbg_info(node);
906         ir_graph *irg = get_irn_irg(block);
907         mips_attr_t *attr;
908         int i, n;
909
910         if (size > 16) {
911                 ir_node     *phi, *projT, *projF, *cmp, *proj, *cond, *jmp, *in[2];
912                 ir_node     *new_bl, *src_phi, *dst_phi, *mem_phi, *add;
913                 ir_mode     *p_mode = get_irn_mode(src);
914                 ir_node     *ld[4];
915
916                 /* build the control loop */
917                 in[0] = in[1] = new_r_Unknown(irg, mode_X);
918
919                 new_bl = new_r_Block(irg, 2, in);
920
921                 in[0] = cnt = new_Const_long(mode_Is, (size >> 4));
922         in[1] = new_r_Unknown(irg, mode_Is);
923                 phi   = new_r_Phi(irg, new_bl, 2, in, mode_Is);
924
925                 sub = new_rd_Sub(dbg, irg, new_bl, phi, new_Const_long(mode_Is, -1), mode_Is);
926                 set_Phi_pred(phi, 1, sub);
927
928                 cmp = new_rd_Cmp(dbg, irg, new_bl, sub, new_Const_long(mode_Is, 0));
929                 proj = new_r_Proj(irg, new_bl, cmp, mode_b, pn_Cmp_Lg);
930                 cond = new_rd_Cond(dbg, irg, new_bl, proj);
931
932                 projT = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_true);
933                 projF = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_false);
934
935                 jmp = get_Block_cfgpred(block, 0);
936                 set_Block_cfgpred(block, 0, projF);
937
938                 set_Block_cfgpred(new_bl, 0, jmp);
939                 set_Block_cfgpred(new_bl, 1, projT);
940
941                 size &= 0xF;
942
943                 /* build the copy */
944                 in[0]   = src;
945         in[1]   = new_r_Unknown(irg, p_mode);
946                 src_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
947
948                 in[0]   = dst;
949                 dst_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
950
951                 add = new_rd_Add(dbg, irg, new_bl, src_phi, new_Const_long(mode_Is, 16), p_mode);
952                 set_Phi_pred(src_phi, 1, add);
953                 add = new_rd_Add(dbg, irg, new_bl, dst_phi, new_Const_long(mode_Is, 16), p_mode);
954                 set_Phi_pred(dst_phi, 1, add);
955
956                 in[0]   = mem;
957         in[1]   = new_r_Unknown(irg, mode_M);
958                 mem_phi = new_r_Phi(irg, new_bl, 2, in, mode_M);
959
960                 src = src_phi;
961                 dst = dst_phi;
962
963                 /* create 4 parallel loads */
964                 for (i = 0; i < 4; ++i) {
965                         ir_node *load;
966
967                         load = new_rd_mips_load_r(dbg, irg, new_bl, mem_phi, src, mode_T);
968                         attr = get_mips_attr(load);
969                         attr->modes.load_store_mode = mode_Iu;
970                         attr->tv = new_tarval_from_long(i * 4, mode_Iu);
971
972                         ld[i] = new_rd_Proj(dbg, irg, new_bl, load, mode_Iu, pn_Load_res);
973                 }
974
975                 /* create 4 parallel stores */
976                 for (i = 0; i < 4; ++i) {
977                         ir_node *store;
978
979                         store = new_rd_mips_store_r(dbg, irg, new_bl, mem_phi, dst, ld[i], mode_T);
980                         attr = get_mips_attr(store);
981                         attr->modes.load_store_mode = mode_Iu;
982                         attr->tv = new_tarval_from_long(i * 4, mode_Iu);
983
984                         mm[i] = new_rd_Proj(dbg, irg, new_bl, store, mode_M, pn_Store_M);
985                 }
986                 mem = new_r_Sync(irg, new_bl, 4, mm);
987                 result = mem;
988                 set_Phi_pred(mem_phi, 1, mem);
989         }
990
991         // output store/loads manually
992         n = 0;
993         for(i = size; i > 0; ) {
994                 ir_mode *mode;
995                 ir_node *load, *store, *projv;
996                 int offset = size - i;
997                 if(i >= 4) {
998                         mode = mode_Iu;
999                         i -= 4;
1000                 } else if(i >= 2) {
1001                         mode = mode_Hu;
1002                         i -= 2;
1003                 } else {
1004                         mode = mode_Bu;
1005                         i -= 1;
1006                 }
1007
1008                 load = new_rd_mips_load_r(dbg, irg, block, mem, src, mode_T);
1009                 attr = get_mips_attr(load);
1010                 attr->modes.load_store_mode = mode;
1011                 attr->tv = new_tarval_from_long(offset, mode_Iu);
1012
1013                 projv = new_rd_Proj(dbg, irg, block, load, mode, pn_Load_res);
1014
1015                 store = new_rd_mips_store_r(dbg, irg, block, mem, dst, projv, mode_T);
1016                 attr = get_mips_attr(store);
1017                 attr->modes.load_store_mode = mode;
1018                 attr->tv = new_tarval_from_long(offset, mode_Iu);
1019
1020                 mm[n] = new_rd_Proj(dbg, irg, block, store, mode_M, pn_Store_M);
1021                 n++;
1022         }
1023
1024         if(n > 0) {
1025                 result = new_r_Sync(irg, block, n, mm);
1026         } else if(n == 1) {
1027                 result = mm[0];
1028         }
1029
1030         return result;
1031 }
1032
1033 static void mips_fix_CopyB_Proj(mips_transform_env_t* env) {
1034         ir_node *node = env->irn;
1035         long n = get_Proj_proj(node);
1036
1037         if(n == pn_CopyB_M_except) {
1038                 panic("Unsupported Proj from CopyB");
1039         } else if(n == pn_CopyB_M_regular) {
1040                 set_Proj_proj(node, pn_Store_M);
1041         } else if(n == pn_CopyB_M_except) {
1042                 set_Proj_proj(node, pn_Store_X_except);
1043         }
1044 }
1045 #endif
1046
1047 static void mips_transform_Spill(mips_transform_env_t* env) {
1048         ir_node   *node = env->irn;
1049         ir_node   *sched_point = NULL;
1050         ir_node   *store;
1051         ir_node   *nomem = new_rd_NoMem(env->irg);
1052         ir_node   *ptr   = get_irn_n(node, 0);
1053         ir_node   *val   = get_irn_n(node, 1);
1054         ir_entity *ent   = be_get_frame_entity(node);
1055
1056         if(sched_is_scheduled(node)) {
1057                 sched_point = sched_prev(node);
1058         }
1059
1060         store = new_rd_mips_sw(env->dbg, env->irg, env->block, ptr, val, nomem,
1061                                ent, 0);
1062
1063         if (sched_point) {
1064                 sched_add_after(sched_point, store);
1065                 sched_remove(node);
1066         }
1067
1068         exchange(node, store);
1069 }
1070
1071 static void mips_transform_Reload(mips_transform_env_t* env) {
1072         ir_node   *node = env->irn;
1073         ir_node   *sched_point = NULL;
1074         ir_node   *load, *proj;
1075         ir_node   *ptr   = get_irn_n(node, 0);
1076         ir_node   *mem   = get_irn_n(node, 1);
1077         ir_entity *ent   = be_get_frame_entity(node);
1078         const arch_register_t* reg;
1079
1080         if(sched_is_scheduled(node)) {
1081                 sched_point = sched_prev(node);
1082         }
1083
1084         load = new_rd_mips_lw(env->dbg, env->irg, env->block, ptr, mem, ent, 0);
1085
1086         proj = new_rd_Proj(env->dbg, env->irg, env->block, load, mode_Iu, pn_mips_lw_res);
1087
1088         if (sched_point) {
1089                 sched_add_after(sched_point, load);
1090
1091                 sched_remove(node);
1092         }
1093
1094         /* copy the register from the old node to the new Load */
1095         reg = arch_get_irn_register(node);
1096         arch_set_irn_register(proj, reg);
1097
1098         exchange(node, proj);
1099 }
1100
1101 #if 0
1102 static ir_node *gen_AddSP(ir_node *node)
1103 {
1104         ir_node *node = env->irn;
1105         ir_node *op1, *op2;
1106         ir_node *add;
1107         const arch_register_t *reg;
1108
1109         op1 = get_irn_n(node, 0);
1110         op2 = get_irn_n(node, 1);
1111
1112         add = new_rd_mips_addu(env->dbg, env->irg, env->block, op1, op2);
1113
1114         /* copy the register requirements from the old node to the new node */
1115         reg = arch_get_irn_register(node);
1116         arch_set_irn_register(add, reg);
1117
1118         return add;
1119 }
1120 #endif
1121
1122 /*********************************************************
1123  *                  _             _      _
1124  *                 (_)           | |    (_)
1125  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
1126  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
1127  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
1128  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
1129  *
1130  *********************************************************/
1131
1132 typedef ir_node *(*mips_transform_func) (ir_node *node);
1133
1134 static void register_transformer(ir_op *op, mips_transform_func func)
1135 {
1136         assert(op->ops.generic == NULL);
1137         op->ops.generic = (op_func) func;
1138 }
1139
1140 static void register_transformers(void)
1141 {
1142         clear_irp_opcodes_generic_func();
1143
1144         register_transformer(op_Add, gen_Add);
1145         register_transformer(op_Sub, gen_Sub);
1146         register_transformer(op_And, gen_And);
1147         register_transformer(op_Or,  gen_Or);
1148         register_transformer(op_Eor, gen_Eor);
1149         register_transformer(op_Shl, gen_Shl);
1150         register_transformer(op_Shr, gen_Shr);
1151         register_transformer(op_Shrs, gen_Shrs);
1152         register_transformer(op_Not, gen_Not);
1153         register_transformer(op_Minus, gen_Minus);
1154         register_transformer(op_Div, gen_Div);
1155         register_transformer(op_Mod, gen_Mod);
1156         register_transformer(op_DivMod, gen_DivMod);
1157         register_transformer(op_Abs, gen_Abs);
1158         register_transformer(op_Load, gen_Load);
1159         register_transformer(op_Store, gen_Store);
1160         register_transformer(op_Cond, gen_Cond);
1161         register_transformer(op_Conv, gen_Conv);
1162         register_transformer(op_Const, gen_Const);
1163         register_transformer(op_SymConst, gen_SymConst);
1164         register_transformer(op_Unknown, gen_Unknown);
1165         register_transformer(op_Proj, gen_Proj);
1166         register_transformer(op_Phi, gen_Phi);
1167 }
1168
1169 void mips_transform_graph(mips_code_gen_t *cg)
1170 {
1171         register_transformers();
1172         be_transform_graph(cg->birg, NULL);
1173 }
1174
1175 /**
1176  * Calls the transform functions for Spill and Reload.
1177  */
1178 void mips_after_ra_walker(ir_node *node, void *env) {
1179         mips_code_gen_t *cg = env;
1180         mips_transform_env_t tenv;
1181
1182         if (is_Block(node))
1183                 return;
1184
1185         tenv.block = get_nodes_block(node);
1186         tenv.dbg   = get_irn_dbg_info(node);
1187         tenv.irg   = current_ir_graph;
1188         tenv.irn   = node;
1189         tenv.mode  = get_irn_mode(node);
1190         tenv.cg    = cg;
1191
1192         if (be_is_Reload(node)) {
1193                 mips_transform_Reload(&tenv);
1194         } else if (be_is_Spill(node)) {
1195                 mips_transform_Spill(&tenv);
1196         }
1197 }