2 * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
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.
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.
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
22 * @brief The codegenrator (transform FIRM into mips FIRM
23 * @author Matthias Braun, Mehdi
33 #include "irgraph_t.h"
45 #include "../benode_t.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"
53 #include "mips_nodes_attr.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"
61 #include "gen_mips_regalloc_if.h"
63 /** hold the current code generator during transformation */
64 static mips_code_gen_t *env_cg = NULL;
66 /****************************************************************************************************
68 * | | | | / _| | | (_)
69 * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
70 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
71 * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
72 * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
74 ****************************************************************************************************/
76 typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg,
77 ir_node *block, ir_node *left, ir_node *right);
79 static INLINE int mode_needs_gp_reg(ir_mode *mode) {
80 return mode_is_int(mode) || mode_is_character(mode)
81 || mode_is_reference(mode);
84 ir_node *mips_create_Immediate(long val)
86 ir_graph *irg = current_ir_graph;
87 ir_node *block = get_irg_start_block(irg);
88 const arch_register_t **slots;
91 assert(val >= -32768 && val <= 32767);
92 res = new_rd_mips_Immediate(NULL, irg, block, MIPS_IMM_CONST, NULL,
94 slots = get_mips_slots(res);
95 slots[0] = &mips_gp_regs[REG_GP_NOREG];
100 ir_node* mips_create_zero(void)
102 ir_graph *irg = current_ir_graph;
103 ir_node *block = get_irg_start_block(irg);
104 ir_node *zero = new_rd_mips_zero(NULL, irg, block);
105 const arch_register_t **slots = get_mips_slots(zero);
107 slots[0] = &mips_gp_regs[REG_ZERO];
112 static ir_node *try_create_Immediate(ir_node *node)
121 mode = get_irn_mode(node);
122 if(!mode_needs_gp_reg(mode))
125 tv = get_Const_tarval(node);
126 if(tarval_is_long(tv)) {
127 val = get_tarval_long(tv);
128 } else if(tarval_is_null(tv)) {
131 ir_fprintf(stderr, "Optimisation Warning: tarval %+F is not a long?\n",
136 if(val < -32768 || val > 32767)
139 return mips_create_Immediate(val);
142 static void create_binop_operands(ir_node **new_left, ir_node **new_right,
143 ir_node *left, ir_node *right,
146 *new_right = try_create_Immediate(right);
147 if(*new_right != NULL) {
148 *new_left = be_transform_node(left);
152 *new_right = try_create_Immediate(left);
153 if(*new_right != NULL) {
154 *new_left = be_transform_node(right);
159 *new_left = be_transform_node(left);
160 *new_right = be_transform_node(right);
163 static ir_node *gen_binop(ir_node *node, ir_node *left, ir_node *right,
164 construct_binop_func func, int supports_immediate)
166 ir_graph *irg = current_ir_graph;
167 dbg_info *dbgi = get_irn_dbg_info(node);
168 ir_node *block = be_transform_node(get_nodes_block(node));
170 ir_node *new_left, *new_right;
172 assert(mode_needs_gp_reg(get_irn_mode(node)));
174 if(supports_immediate) {
175 int is_commutative = is_op_commutative(get_irn_op(node));
176 create_binop_operands(&new_left, &new_right, left, right,
179 new_left = be_transform_node(left);
180 new_right = be_transform_node(right);
183 res = func(dbgi, irg, block, new_left, new_right);
188 static ir_node *gen_Add(ir_node *node)
190 /* TODO: match add(symconst, const) */
191 return gen_binop(node, get_Add_left(node), get_Add_right(node),
192 new_rd_mips_addu, 1);
195 static ir_node *gen_Sub(ir_node *node)
197 return gen_binop(node, get_Sub_left(node), get_Sub_right(node),
198 new_rd_mips_addu, 0);
201 static ir_node *gen_And(ir_node *node)
203 return gen_binop(node, get_Add_left(node), get_Add_right(node),
207 static ir_node *gen_Or(ir_node *node)
209 return gen_binop(node, get_Add_left(node), get_Add_right(node),
213 static ir_node *gen_Eor(ir_node *node)
215 return gen_binop(node, get_Add_left(node), get_Add_right(node),
219 static ir_node *gen_Shl(ir_node *node)
221 return gen_binop(node, get_Add_left(node), get_Add_right(node),
225 static ir_node *gen_Shr(ir_node *node)
227 return gen_binop(node, get_Add_left(node), get_Add_right(node),
231 static ir_node *gen_Shrs(ir_node *node)
233 return gen_binop(node, get_Add_left(node), get_Add_right(node),
237 static ir_node *gen_Not(ir_node *node)
239 ir_graph *irg = current_ir_graph;
240 dbg_info *dbgi = get_irn_dbg_info(node);
241 ir_node *block = be_transform_node(get_nodes_block(node));
242 ir_node *op = get_Not_op(node);
247 /* we can transform not->or to nor */
249 return gen_binop(op, get_Or_left(op), get_Or_right(op),
253 /* construct (op < 1) */
254 one = mips_create_Immediate(1);
255 new_op = be_transform_node(op);
256 res = new_rd_mips_sltu(dbgi, irg, block, new_op, one);
261 static ir_node *gen_Minus(ir_node *node)
263 ir_graph *irg = current_ir_graph;
264 dbg_info *dbgi = get_irn_dbg_info(node);
265 ir_node *block = be_transform_node(get_nodes_block(node));
266 ir_node *op = get_Minus_op(node);
267 ir_node *new_op = be_transform_node(op);
271 /* construct (0 - op) */
272 zero = mips_create_zero();
273 res = new_rd_mips_subu(dbgi, irg, block, zero, new_op);
278 static ir_node *gen_Abs(ir_node *node)
280 ir_graph *irg = current_ir_graph;
281 dbg_info *dbgi = get_irn_dbg_info(node);
282 ir_node *block = be_transform_node(get_nodes_block(node));
283 ir_node *op = get_Abs_op(node);
284 ir_node *new_op = be_transform_node(op);
285 ir_node *sra_const, *sra, *add, *xor;
287 /* TODO: support other bit sizes... */
288 assert(get_mode_size_bits(get_irn_mode(node)) == 32);
289 sra_const = mips_create_Immediate(31);
290 sra = new_rd_mips_sra(dbgi, irg, block, new_op, sra_const);
291 add = new_rd_mips_addu(dbgi, irg, block, new_op, sra);
292 xor = new_rd_mips_xor(dbgi, irg, block, sra, add);
297 static ir_node* gen_Const(ir_node *node)
299 ir_graph *irg = current_ir_graph;
300 dbg_info *dbgi = get_irn_dbg_info(node);
301 ir_node *block = be_transform_node(get_nodes_block(node));
302 tarval *tv = get_Const_tarval(node);
306 unsigned long val, lower, upper;
308 if(tarval_is_long(tv)) {
309 val = get_tarval_long(tv);
310 } else if(tarval_is_null(tv)) {
313 panic("Can't get value of tarval %+F\n", node);
316 val = get_tarval_long(tv);
318 lower = val & 0xffff;
319 upper = (val >> 16) & 0xffff;
321 upper_node = mips_create_zero();
323 upper_node = new_rd_mips_lui(dbgi, irg, block, MIPS_IMM_CONST, NULL,
330 or_const = mips_create_Immediate(lower);
331 lower_node = new_rd_mips_or(dbgi, irg, block, upper_node, or_const);
336 static ir_node* gen_SymConst(ir_node *node)
338 ir_graph *irg = current_ir_graph;
339 dbg_info *dbgi = get_irn_dbg_info(node);
340 ir_node *block = be_transform_node(get_nodes_block(node));
342 ir_node *lui, *or_const, *or;
344 if(get_SymConst_kind(node) != symconst_addr_ent) {
345 panic("Only address entity symconsts supported in mips backend");
348 entity = get_SymConst_entity(node);
350 lui = new_rd_mips_lui(dbgi, irg, block, MIPS_IMM_SYMCONST_HI,
352 or_const = new_rd_mips_Immediate(dbgi, irg, block,
353 MIPS_IMM_SYMCONST_LO, entity, 0);
354 or = new_rd_mips_or(dbgi, irg, block, lui, or_const);
359 typedef ir_node* (*gen_load_func) (dbg_info *dbg, ir_graph *irg,
360 ir_node *block, ir_node *ptr, ir_node *mem,
361 ir_entity *entity, long offset);
364 * Generates a mips node for a firm Load node
366 static ir_node *gen_Load(ir_node *node)
368 ir_graph *irg = current_ir_graph;
369 dbg_info *dbgi = get_irn_dbg_info(node);
370 ir_node *block = be_transform_node(get_nodes_block(node));
371 ir_node *mem = get_Load_mem(node);
372 ir_node *new_mem = be_transform_node(mem);
373 ir_node *ptr = get_Load_ptr(node);
374 ir_node *new_ptr = be_transform_node(ptr);
375 ir_mode *mode = get_Load_mode(node);
376 int sign = get_mode_sign(mode);
380 ASSERT_NO_FLOAT(mode);
381 assert(mode_needs_gp_reg(mode));
383 /* TODO: make use of offset in ptrs */
385 switch(get_mode_size_bits(mode)) {
387 func = new_rd_mips_lw;
390 func = sign ? new_rd_mips_lh : new_rd_mips_lhu;
393 func = sign ? new_rd_mips_lb : new_rd_mips_lbu;
396 panic("mips backend only support 32, 16, 8 bit loads");
399 res = func(dbgi, irg, block, new_ptr, new_mem, NULL, 0);
400 set_irn_pinned(res, get_irn_pinned(node));
405 typedef ir_node* (*gen_store_func) (dbg_info *dbg, ir_graph *irg,
406 ir_node *block, ir_node *ptr, ir_node *val,
407 ir_node *mem, ir_entity *ent, long offset);
410 * Generates a mips node for a firm Store node
412 static ir_node *gen_Store(ir_node *node)
414 ir_graph *irg = current_ir_graph;
415 dbg_info *dbgi = get_irn_dbg_info(node);
416 ir_node *block = be_transform_node(get_nodes_block(node));
417 ir_node *mem = get_Store_mem(node);
418 ir_node *new_mem = be_transform_node(mem);
419 ir_node *ptr = get_Store_ptr(node);
420 ir_node *new_ptr = be_transform_node(ptr);
421 ir_node *val = get_Store_value(node);
422 ir_node *new_val = be_transform_node(val);
423 ir_mode *mode = get_irn_mode(val);
427 assert(mode_needs_gp_reg(mode));
429 switch(get_mode_size_bits(mode)) {
431 func = new_rd_mips_sw;
434 func = new_rd_mips_sh;
437 func = new_rd_mips_sb;
440 panic("store only supported for 32, 16, 8 bit values in mips backend");
443 res = func(dbgi, irg, block, new_ptr, new_val, new_mem, NULL, 0);
444 set_irn_pinned(res, get_irn_pinned(node));
449 static ir_node *gen_Proj_DivMod(ir_node *node)
451 ir_graph *irg = current_ir_graph;
452 dbg_info *dbgi = get_irn_dbg_info(node);
453 ir_node *block = be_transform_node(get_nodes_block(node));
454 ir_node *divmod = get_Proj_pred(node);
455 ir_node *new_div = be_transform_node(divmod);
456 long pn = get_Proj_proj(node);
459 assert(is_mips_div(new_div) || is_mips_divu(new_div));
461 switch(get_irn_opcode(divmod)) {
465 return new_rd_Proj(dbgi, irg, block, new_div, mode_M,
468 proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
470 return new_rd_mips_mflo(dbgi, irg, block, proj);
477 return new_rd_Proj(dbgi, irg, block, new_div, mode_M,
480 proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
482 return new_rd_mips_mfhi(dbgi, irg, block, proj);
490 return new_rd_Proj(dbgi, irg, block, new_div, mode_M,
492 case pn_DivMod_res_div:
493 proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
495 return new_rd_mips_mflo(dbgi, irg, block, proj);
496 case pn_DivMod_res_mod:
497 proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
499 return new_rd_mips_mfhi(dbgi, irg, block, proj);
507 panic("invalid proj attached to %+F\n", divmod);
510 static ir_node *gen_Proj_Start(ir_node *node)
512 ir_graph *irg = current_ir_graph;
513 dbg_info *dbgi = get_irn_dbg_info(node);
514 ir_node *block = be_transform_node(get_nodes_block(node));
515 long pn = get_Proj_proj(node);
517 if(pn == pn_Start_X_initial_exec) {
518 /* we exchange the projx with a jump */
519 ir_node *jump = new_rd_Jmp(dbgi, irg, block);
522 if(node == be_get_old_anchor(anchor_tls)) {
524 return be_duplicate_node(node);
526 return be_duplicate_node(node);
529 static ir_node *gen_Proj(ir_node *node)
531 ir_graph *irg = current_ir_graph;
532 dbg_info *dbgi = get_irn_dbg_info(node);
533 ir_node *pred = get_Proj_pred(node);
535 switch(get_irn_opcode(pred)) {
543 return gen_Proj_DivMod(node);
546 return gen_Proj_Start(node);
549 assert(get_irn_mode(node) != mode_T);
550 if(mode_needs_gp_reg(get_irn_mode(node))) {
551 ir_node *new_pred = be_transform_node(pred);
552 ir_node *block = be_transform_node(get_nodes_block(node));
553 long pn = get_Proj_proj(node);
555 return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn);
560 return be_duplicate_node(node);
563 static ir_node *gen_Phi(ir_node *node)
565 ir_graph *irg = current_ir_graph;
566 dbg_info *dbgi = get_irn_dbg_info(node);
567 ir_node *block = be_transform_node(get_nodes_block(node));
568 ir_mode *mode = get_irn_mode(node);
571 if(mode_needs_gp_reg(mode)) {
572 assert(get_mode_size_bits(mode) <= 32);
576 /* phi nodes allow loops, so we use the old arguments for now
577 * and fix this later */
578 phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node),
579 get_irn_in(node) + 1);
580 copy_node_attr(node, phi);
581 be_duplicate_deps(node, phi);
583 be_set_transformed_node(node, phi);
584 be_enqueue_preds(node);
591 ir_node *gen_node_for_SwitchCond(mips_transform_env_t *env)
593 ir_node *selector = get_Cond_selector(env->irn);
594 ir_mode *selector_mode = get_irn_mode(selector);
595 ir_node *node = env->irn;
596 dbg_info *dbg = env->dbg;
597 ir_graph *irg = env->irg;
598 ir_node *block = env->block;
599 ir_node *sub, *sltu, *minval_const, *max_const, *switchjmp;
600 ir_node *defaultproj, *defaultproj_succ;
602 long pn, minval, maxval, defaultprojn;
603 const ir_edge_t *edge;
604 ir_node *zero, *two_const, *add, *la, *load, *proj;
605 ir_mode *unsigned_mode;
608 // mode_b conds are handled by gen_node_for_Proj
609 if(get_mode_sort(selector_mode) != irms_int_number)
612 assert(get_mode_size_bits(selector_mode) == 32);
615 defaultprojn = get_Cond_defaultProj(node);
617 // go over all projs to find min-&maxval of the switch
620 foreach_out_edge(node, edge) {
621 ir_node* proj = get_edge_src_irn(edge);
622 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
624 pn = get_Proj_proj(proj);
625 if(pn == defaultprojn) {
635 assert(defaultproj != NULL);
637 // subtract minval from the switch value
640 minval_const = new_rd_Const(dbg, irg, block, selector_mode, new_tarval_from_long(minval, selector_mode));
641 minval_const = gen_node_for_Const(env, dbg, irg, block, minval_const);
642 sub = new_rd_mips_sub(dbg, irg, block, selector, minval_const);
647 // compare if we're above maxval-minval or below zero.
648 // we can do this with 1 compare because we use unsigned mode
649 unsigned_mode = new_ir_mode(get_mode_name(selector_mode),
650 get_mode_sort(selector_mode), get_mode_size_bits(selector_mode),
651 0, get_mode_arithmetic(selector_mode), get_mode_modulo_shift(selector_mode));
653 max_const = new_rd_Const(dbg, irg, block, unsigned_mode, new_tarval_from_long(maxval - minval + 1, unsigned_mode));
654 max_const = gen_node_for_Const(env, dbg, irg, block, max_const);
655 sltu = new_rd_mips_slt(dbg, irg, block, sub, max_const);
657 zero = gen_zero_node(env, dbg, irg, block);
658 beq = new_rd_mips_beq(dbg, irg, block, sltu, zero, mode_T);
660 // attach defaultproj to beq now
661 set_irn_n(defaultproj, 0, beq);
662 set_Proj_proj(defaultproj, 1);
664 two_const = new_rd_Const(dbg, irg, block, unsigned_mode, new_tarval_from_long(2, unsigned_mode));
665 two_const = gen_node_for_Const(env, dbg, irg, block, two_const);
666 sl = new_rd_mips_sl(dbg, irg, block, sub, two_const);
668 la = new_rd_mips_la(dbg, irg, block);
669 add = new_rd_mips_addu(dbg, irg, block, sl, la);
670 load = new_rd_mips_load_r(dbg, irg, block, new_rd_NoMem(irg), add, mode_T);
671 attr = get_mips_attr(load);
672 attr->modes.load_store_mode = mode_Iu;
673 attr->tv = new_tarval_from_long(0, mode_Iu);
675 proj = new_rd_Proj(dbg, irg, block, load, mode_Iu, pn_Load_res);
677 switchjmp = new_rd_mips_SwitchJump(dbg, irg, block, proj, mode_T);
678 attr = get_mips_attr(switchjmp);
679 attr->switch_default_pn = defaultprojn;
681 edge = get_irn_out_edge_first(defaultproj);
682 defaultproj_succ = get_edge_src_irn(edge);
683 attr->symconst_id = new_id_from_str(mips_get_block_label(defaultproj_succ));
685 attr = get_mips_attr(la);
686 attr->symconst_id = new_id_from_str(mips_get_jumptbl_label(switchjmp));
692 static ir_node *gen_Cond(ir_node *node)
694 ir_graph *irg = current_ir_graph;
695 dbg_info *dbgi = get_irn_dbg_info(node);
696 ir_node *block = get_nodes_block(node);
697 ir_node *sel_proj = get_Cond_selector(node);
698 ir_node *cmp = get_Proj_pred(sel_proj);
699 ir_node *left = get_Cmp_left(cmp);
700 ir_node *new_left = be_transform_node(left);
701 ir_node *right = get_Cmp_right(cmp);
702 ir_node *new_right = be_transform_node(right);
703 long pnc = get_Proj_proj(sel_proj);
708 /* TODO: use blez & co. when possible */
714 panic("mips backend can't handle unoptimized constant Cond");
717 res = new_rd_mips_beq(dbgi, irg, block, new_left, new_right);
721 zero = mips_create_zero();
722 slt = new_rd_mips_slt(dbgi, irg, block, new_left, new_right);
723 res = new_rd_mips_bne(dbgi, irg, block, slt, zero);
727 zero = mips_create_zero();
728 slt = new_rd_mips_slt(dbgi, irg, block, new_right, new_left);
729 res = new_rd_mips_beq(dbgi, irg, block, slt, zero);
733 zero = mips_create_zero();
734 slt = new_rd_mips_slt(dbgi, irg, block, new_right, new_left);
735 res = new_rd_mips_bne(dbgi, irg, block, slt, zero);
739 zero = mips_create_zero();
740 slt = new_rd_mips_slt(dbgi, irg, block, new_right, new_left);
741 res = new_rd_mips_bne(dbgi, irg, block, slt, zero);
745 res = new_rd_mips_bne(dbgi, irg, block, new_left, new_right);
749 panic("mips backend doesn't handle unordered compares yet");
755 static ir_node *gen_Conv(ir_node *node)
757 ir_graph *irg = current_ir_graph;
758 dbg_info *dbgi = get_irn_dbg_info(node);
759 ir_node *block = be_transform_node(get_nodes_block(node));
760 ir_node *op = get_Conv_op(node);
761 ir_node *new_op = be_transform_node(op);
762 ir_mode *src_mode = get_irn_mode(op);
763 ir_mode *dst_mode = get_irn_mode(node);
764 int src_size = get_mode_size_bits(src_mode);
765 int dst_size = get_mode_size_bits(dst_mode);
768 assert(mode_needs_gp_reg(src_mode));
769 assert(mode_needs_gp_reg(dst_mode));
771 /* we only need to do something on upconvs */
772 if(src_size >= dst_size) {
773 /* unnecessary conv */
777 if(mode_is_signed(src_mode)) {
779 res = new_rd_mips_seb(dbgi, irg, block, new_op);
780 } else if(src_size == 16) {
781 res = new_rd_mips_seh(dbgi, irg, block, new_op);
783 panic("invalid conv %+F\n", node);
789 and_const = mips_create_Immediate(0xff);
790 } else if(src_size == 16) {
791 and_const = mips_create_Immediate(0xffff);
793 panic("invalid conv %+F\n", node);
795 res = new_rd_mips_and(dbgi, irg, block, new_op, and_const);
801 static ir_node *create_div(ir_node *node, ir_node *left, ir_node *right,
804 ir_graph *irg = current_ir_graph;
805 dbg_info *dbgi = get_irn_dbg_info(node);
806 ir_node *block = be_transform_node(get_nodes_block(node));
807 ir_node *new_left = be_transform_node(left);
808 ir_node *new_right = be_transform_node(right);
811 if(mode_is_signed(mode)) {
812 res = new_rd_mips_div(dbgi, irg, block, new_left, new_right);
814 res = new_rd_mips_divu(dbgi, irg, block, new_left, new_right);
817 set_irn_pinned(res, get_irn_pinned(node));
822 static ir_node *gen_DivMod(ir_node *node)
824 return create_div(node, get_DivMod_left(node), get_DivMod_right(node),
825 get_DivMod_resmode(node));
828 static ir_node *gen_Div(ir_node *node)
830 return create_div(node, get_Div_left(node), get_Div_right(node),
831 get_Div_resmode(node));
834 static ir_node *gen_Mod(ir_node *node)
836 return create_div(node, get_Mod_left(node), get_Mod_right(node),
837 get_Mod_resmode(node));
841 static ir_node *gen_node_for_Mul(mips_transform_env_t *env) {
842 ir_node *node = env->irn;
846 ir_mode *mode = get_irn_mode(node);
848 op1 = get_Mul_left(node);
849 op2 = get_Mul_right(node);
851 assert(get_mode_size_bits(env->mode) == 32);
852 assert(get_mode_size_bits(get_irn_mode(op1)) == get_mode_size_bits(env->mode));
853 assert(get_mode_size_bits(get_irn_mode(op2)) == get_mode_size_bits(env->mode));
855 if(mode_is_signed(mode)) {
856 mul = new_rd_mips_mult(env->dbg, env->irg, env->block, get_Mul_left(node), get_Mul_right(node));
858 mul = new_rd_mips_multu(env->dbg, env->irg, env->block, get_Mul_left(node), get_Mul_right(node));
860 mflo = new_rd_mips_mflo(env->dbg, env->irg, env->block, mul);
866 ir_node *gen_node_for_IJmp(mips_transform_env_t *env) {
867 ir_graph *irg = env->irg;
868 ir_node *node = env->irn;
869 dbg_info *dbg = get_irn_dbg_info(node);
870 ir_node *block = get_nodes_block(node);
871 ir_node *target = get_IJmp_target(node);
873 return new_rd_mips_jr(dbg, irg, block, target);
877 ir_node *gen_node_for_Rot(mips_transform_env_t *env) {
878 ir_node *node = env->irn;
879 ir_node *subu, *srlv, *sllv, *or;
881 subu = new_rd_mips_subuzero(env->dbg, env->irg, env->block, get_Rot_right(node));
882 srlv = new_rd_mips_srlv(env->dbg, env->irg, env->block, get_Rot_left(node), subu);
883 sllv = new_rd_mips_sllv(env->dbg, env->irg, env->block, get_Rot_left(node), get_Rot_right(node));
884 or = new_rd_mips_or(env->dbg, env->irg, env->block, sllv, srlv);
890 static ir_node *gen_Unknown(ir_node *node)
893 assert(mode_needs_gp_reg(get_irn_mode(node)));
894 return mips_create_zero();
899 * lower a copyB into standard Firm assembler :-)
901 ir_node *gen_code_for_CopyB(ir_node *block, ir_node *node) {
903 ir_node *dst = get_CopyB_dst(node);
904 ir_node *src = get_CopyB_src(node);
905 ir_type *type = get_CopyB_type(node);
906 ir_node *mem = get_CopyB_mem(node);
908 ir_node *result = NULL;
909 int size = get_type_size_bytes(type);
910 dbg_info *dbg = get_irn_dbg_info(node);
911 ir_graph *irg = get_irn_irg(block);
916 ir_node *phi, *projT, *projF, *cmp, *proj, *cond, *jmp, *in[2];
917 ir_node *new_bl, *src_phi, *dst_phi, *mem_phi, *add;
918 ir_mode *p_mode = get_irn_mode(src);
921 /* build the control loop */
922 in[0] = in[1] = new_r_Unknown(irg, mode_X);
924 new_bl = new_r_Block(irg, 2, in);
926 in[0] = cnt = new_Const_long(mode_Is, (size >> 4));
927 in[1] = new_r_Unknown(irg, mode_Is);
928 phi = new_r_Phi(irg, new_bl, 2, in, mode_Is);
930 sub = new_rd_Sub(dbg, irg, new_bl, phi, new_Const_long(mode_Is, -1), mode_Is);
931 set_Phi_pred(phi, 1, sub);
933 cmp = new_rd_Cmp(dbg, irg, new_bl, sub, new_Const_long(mode_Is, 0));
934 proj = new_r_Proj(irg, new_bl, cmp, mode_b, pn_Cmp_Lg);
935 cond = new_rd_Cond(dbg, irg, new_bl, proj);
937 projT = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_true);
938 projF = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_false);
940 jmp = get_Block_cfgpred(block, 0);
941 set_Block_cfgpred(block, 0, projF);
943 set_Block_cfgpred(new_bl, 0, jmp);
944 set_Block_cfgpred(new_bl, 1, projT);
950 in[1] = new_r_Unknown(irg, p_mode);
951 src_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
954 dst_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
956 add = new_rd_Add(dbg, irg, new_bl, src_phi, new_Const_long(mode_Is, 16), p_mode);
957 set_Phi_pred(src_phi, 1, add);
958 add = new_rd_Add(dbg, irg, new_bl, dst_phi, new_Const_long(mode_Is, 16), p_mode);
959 set_Phi_pred(dst_phi, 1, add);
962 in[1] = new_r_Unknown(irg, mode_M);
963 mem_phi = new_r_Phi(irg, new_bl, 2, in, mode_M);
968 /* create 4 parallel loads */
969 for (i = 0; i < 4; ++i) {
972 load = new_rd_mips_load_r(dbg, irg, new_bl, mem_phi, src, mode_T);
973 attr = get_mips_attr(load);
974 attr->modes.load_store_mode = mode_Iu;
975 attr->tv = new_tarval_from_long(i * 4, mode_Iu);
977 ld[i] = new_rd_Proj(dbg, irg, new_bl, load, mode_Iu, pn_Load_res);
980 /* create 4 parallel stores */
981 for (i = 0; i < 4; ++i) {
984 store = new_rd_mips_store_r(dbg, irg, new_bl, mem_phi, dst, ld[i], mode_T);
985 attr = get_mips_attr(store);
986 attr->modes.load_store_mode = mode_Iu;
987 attr->tv = new_tarval_from_long(i * 4, mode_Iu);
989 mm[i] = new_rd_Proj(dbg, irg, new_bl, store, mode_M, pn_Store_M);
991 mem = new_r_Sync(irg, new_bl, 4, mm);
993 set_Phi_pred(mem_phi, 1, mem);
996 // output store/loads manually
998 for(i = size; i > 0; ) {
1000 ir_node *load, *store, *projv;
1001 int offset = size - i;
1013 load = new_rd_mips_load_r(dbg, irg, block, mem, src, mode_T);
1014 attr = get_mips_attr(load);
1015 attr->modes.load_store_mode = mode;
1016 attr->tv = new_tarval_from_long(offset, mode_Iu);
1018 projv = new_rd_Proj(dbg, irg, block, load, mode, pn_Load_res);
1020 store = new_rd_mips_store_r(dbg, irg, block, mem, dst, projv, mode_T);
1021 attr = get_mips_attr(store);
1022 attr->modes.load_store_mode = mode;
1023 attr->tv = new_tarval_from_long(offset, mode_Iu);
1025 mm[n] = new_rd_Proj(dbg, irg, block, store, mode_M, pn_Store_M);
1030 result = new_r_Sync(irg, block, n, mm);
1038 static void mips_fix_CopyB_Proj(mips_transform_env_t* env) {
1039 ir_node *node = env->irn;
1040 long n = get_Proj_proj(node);
1042 if(n == pn_CopyB_M_except) {
1044 } else if(n == pn_CopyB_M_regular) {
1045 set_Proj_proj(node, pn_Store_M);
1046 } else if(n == pn_CopyB_M_except) {
1047 set_Proj_proj(node, pn_Store_X_except);
1052 static void mips_transform_Spill(mips_transform_env_t* env) {
1053 ir_node *node = env->irn;
1054 ir_node *sched_point = NULL;
1056 ir_node *nomem = new_rd_NoMem(env->irg);
1057 ir_node *ptr = get_irn_n(node, 0);
1058 ir_node *val = get_irn_n(node, 1);
1059 ir_entity *ent = be_get_frame_entity(node);
1061 if(sched_is_scheduled(node)) {
1062 sched_point = sched_prev(node);
1065 store = new_rd_mips_sw(env->dbg, env->irg, env->block, ptr, val, nomem,
1069 sched_add_after(sched_point, store);
1073 exchange(node, store);
1076 static void mips_transform_Reload(mips_transform_env_t* env) {
1077 ir_node *node = env->irn;
1078 ir_node *sched_point = NULL;
1079 ir_node *load, *proj;
1080 ir_node *ptr = get_irn_n(node, 0);
1081 ir_node *mem = get_irn_n(node, 1);
1082 ir_entity *ent = be_get_frame_entity(node);
1083 const arch_register_t* reg;
1085 if(sched_is_scheduled(node)) {
1086 sched_point = sched_prev(node);
1089 load = new_rd_mips_lw(env->dbg, env->irg, env->block, ptr, mem, ent, 0);
1091 proj = new_rd_Proj(env->dbg, env->irg, env->block, load, mode_Iu, pn_mips_lw_res);
1094 sched_add_after(sched_point, load);
1099 /* copy the register from the old node to the new Load */
1100 reg = arch_get_irn_register(env->cg->arch_env, node);
1101 arch_set_irn_register(env->cg->arch_env, proj, reg);
1103 exchange(node, proj);
1107 static ir_node *gen_node_for_StackParam(mips_transform_env_t *env)
1109 ir_node *node = env->irn;
1110 ir_node *sp = get_irn_n(node, 0);
1112 ir_node *nomem = new_rd_NoMem(env->irg);
1116 load = new_rd_mips_load_r(env->dbg, env->irg, env->block, nomem, sp, mode_T);
1117 attr = get_mips_attr(load);
1118 attr->stack_entity = be_get_frame_entity(node);
1119 attr->modes.load_store_mode = env->mode;
1121 proj = new_rd_Proj(env->dbg, env->irg, env->block, load, env->mode, pn_Load_res);
1128 static ir_node *gen_AddSP(ir_node *node)
1130 ir_node *node = env->irn;
1133 const arch_register_t *reg;
1135 op1 = get_irn_n(node, 0);
1136 op2 = get_irn_n(node, 1);
1138 add = new_rd_mips_addu(env->dbg, env->irg, env->block, op1, op2);
1140 /* copy the register requirements from the old node to the new node */
1141 reg = arch_get_irn_register(env->cg->arch_env, node);
1142 arch_set_irn_register(env->cg->arch_env, add, reg);
1148 /*********************************************************
1151 * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
1152 * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
1153 * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
1154 * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
1156 *********************************************************/
1158 static ir_node *gen_Bad(ir_node *node)
1160 panic("Unexpected node %+F found in mips transform phase.\n", node);
1164 static void register_transformers(void)
1166 clear_irp_opcodes_generic_func();
1168 op_Add->ops.generic = (op_func) gen_Add;
1169 op_Sub->ops.generic = (op_func) gen_Sub;
1170 op_And->ops.generic = (op_func) gen_And;
1171 op_Or->ops.generic = (op_func) gen_Or;
1172 op_Eor->ops.generic = (op_func) gen_Eor;
1173 op_Shl->ops.generic = (op_func) gen_Shl;
1174 op_Shr->ops.generic = (op_func) gen_Shr;
1175 op_Shrs->ops.generic = (op_func) gen_Shrs;
1176 op_Not->ops.generic = (op_func) gen_Not;
1177 op_Minus->ops.generic = (op_func) gen_Minus;
1178 op_Div->ops.generic = (op_func) gen_Div;
1179 op_Mod->ops.generic = (op_func) gen_Mod;
1180 op_DivMod->ops.generic = (op_func) gen_DivMod;
1181 op_Abs->ops.generic = (op_func) gen_Abs;
1182 op_Load->ops.generic = (op_func) gen_Load;
1183 op_Store->ops.generic = (op_func) gen_Store;
1184 op_Cond->ops.generic = (op_func) gen_Cond;
1185 op_Conv->ops.generic = (op_func) gen_Conv;
1186 op_Const->ops.generic = (op_func) gen_Const;
1187 op_SymConst->ops.generic = (op_func) gen_SymConst;
1188 op_Unknown->ops.generic = (op_func) gen_Unknown;
1189 op_Proj->ops.generic = (op_func) gen_Proj;
1190 op_Phi->ops.generic = (op_func) gen_Phi;
1192 op_Raise->ops.generic = (op_func) gen_Bad;
1193 op_Sel->ops.generic = (op_func) gen_Bad;
1194 op_InstOf->ops.generic = (op_func) gen_Bad;
1195 op_Cast->ops.generic = (op_func) gen_Bad;
1196 op_Free->ops.generic = (op_func) gen_Bad;
1197 op_Tuple->ops.generic = (op_func) gen_Bad;
1198 op_Id->ops.generic = (op_func) gen_Bad;
1199 op_Confirm->ops.generic = (op_func) gen_Bad;
1200 op_Filter->ops.generic = (op_func) gen_Bad;
1201 op_CallBegin->ops.generic = (op_func) gen_Bad;
1202 op_EndReg->ops.generic = (op_func) gen_Bad;
1203 op_EndExcept->ops.generic = (op_func) gen_Bad;
1208 * Transforms the given firm node (and maybe some other related nodes)
1209 * into one or more assembler nodes.
1211 * @param node the firm node
1212 * @param env the debug module
1214 void mips_transform_node(ir_node *node, void *env) {
1215 mips_code_gen_t *cgenv = (mips_code_gen_t *)env;
1216 ir_opcode code = get_irn_opcode(node);
1217 ir_node *asm_node = node;
1218 mips_transform_env_t tenv;
1223 tenv.block = get_nodes_block(node);
1224 tenv.dbg = get_irn_dbg_info(node);
1225 tenv.irg = current_ir_graph;
1227 tenv.mode = get_irn_mode(node);
1230 #define UNOP(firm_opcode, mips_nodetype) case iro_##firm_opcode: asm_node = mips_gen_##mips_nodetype(&tenv, get_##firm_opcode##_op(node)); break
1231 #define BINOP(firm_opcode, mips_nodetype) case iro_##firm_opcode: asm_node = mips_gen_##mips_nodetype(&tenv, get_##firm_opcode##_left(node), get_##firm_opcode##_right(node)); break
1232 #define IGN(a) case iro_##a: break
1233 #define BAD(a) case iro_##a: goto bad
1247 asm_node = gen_node_for_Abs(&tenv);
1251 asm_node = gen_node_for_Rot(&tenv);
1255 asm_node = gen_node_for_Div(&tenv);
1259 asm_node = gen_node_for_Mod(&tenv);
1263 asm_node = gen_node_for_Load(&tenv);
1267 asm_node = gen_node_for_Store(&tenv);
1271 asm_node = gen_node_for_Proj(&tenv);
1275 asm_node = gen_node_for_Conv(&tenv);
1279 asm_node = gen_node_for_DivMod(&tenv);
1283 asm_node = gen_node_for_Mul(&tenv);
1287 asm_node = gen_node_for_Jmp(&tenv);
1291 asm_node = gen_node_for_IJmp(&tenv);
1295 asm_node = gen_node_for_Unknown(&tenv);
1299 asm_node = gen_node_for_Cond(&tenv);
1303 asm_node = gen_node_for_Phi(&tenv);
1306 /* TODO: implement these nodes */
1309 /* You probably don't need to handle the following nodes */
1311 // call is handled in the emit phase
1313 // Cmp is handled together with Cond
1342 if(be_is_StackParam(node)) {
1343 //asm_node = gen_node_for_StackParam(&tenv);
1344 } else if(be_is_AddSP(node)) {
1345 asm_node = gen_node_for_AddSP(&tenv);
1350 fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
1354 if (asm_node != node) {
1355 exchange(node, asm_node);
1360 void mips_transform_graph(mips_code_gen_t *cg)
1363 register_transformers();
1364 be_transform_graph(cg->birg, NULL, cg);
1368 * Calls the transform functions for Spill and Reload.
1370 void mips_after_ra_walker(ir_node *node, void *env) {
1371 mips_code_gen_t *cg = env;
1372 mips_transform_env_t tenv;
1377 tenv.block = get_nodes_block(node);
1378 tenv.dbg = get_irn_dbg_info(node);
1379 tenv.irg = current_ir_graph;
1381 tenv.mode = get_irn_mode(node);
1384 if (be_is_Reload(node)) {
1385 mips_transform_Reload(&tenv);
1386 } else if (be_is_Spill(node)) {
1387 mips_transform_Spill(&tenv);