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