2 * Copyright (C) 1995-2008 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 /****************************************************************************************************
65 * | | | | / _| | | (_)
66 * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
67 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
68 * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
69 * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
71 ****************************************************************************************************/
73 typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg,
74 ir_node *block, ir_node *left, ir_node *right);
76 static INLINE int mode_needs_gp_reg(ir_mode *mode) {
77 return mode_is_int(mode) || mode_is_reference(mode);
80 ir_node *mips_create_Immediate(long val)
82 ir_graph *irg = current_ir_graph;
83 ir_node *block = get_irg_start_block(irg);
84 const arch_register_t **slots;
87 assert(val >= -32768 && val <= 32767);
88 res = new_rd_mips_Immediate(NULL, irg, block, MIPS_IMM_CONST, NULL,
90 slots = get_mips_slots(res);
91 slots[0] = &mips_gp_regs[REG_GP_NOREG];
96 ir_node* mips_create_zero(void)
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);
103 slots[0] = &mips_gp_regs[REG_ZERO];
108 static ir_node *try_create_Immediate(ir_node *node)
117 mode = get_irn_mode(node);
118 if(!mode_needs_gp_reg(mode))
121 tv = get_Const_tarval(node);
122 if(tarval_is_long(tv)) {
123 val = get_tarval_long(tv);
125 ir_fprintf(stderr, "Optimisation Warning: tarval %+F is not a long?\n",
130 if(val < -32768 || val > 32767)
133 return mips_create_Immediate(val);
136 static void create_binop_operands(ir_node **new_left, ir_node **new_right,
137 ir_node *left, ir_node *right,
140 *new_right = try_create_Immediate(right);
141 if(*new_right != NULL) {
142 *new_left = be_transform_node(left);
146 *new_right = try_create_Immediate(left);
147 if(*new_right != NULL) {
148 *new_left = be_transform_node(right);
153 *new_left = be_transform_node(left);
154 *new_right = be_transform_node(right);
157 static ir_node *gen_binop(ir_node *node, ir_node *left, ir_node *right,
158 construct_binop_func func, int supports_immediate)
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));
164 ir_node *new_left, *new_right;
166 assert(mode_needs_gp_reg(get_irn_mode(node)));
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,
173 new_left = be_transform_node(left);
174 new_right = be_transform_node(right);
177 res = func(dbgi, irg, block, new_left, new_right);
182 static ir_node *gen_Add(ir_node *node)
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);
189 static ir_node *gen_Sub(ir_node *node)
191 return gen_binop(node, get_Sub_left(node), get_Sub_right(node),
192 new_rd_mips_addu, 0);
195 static ir_node *gen_And(ir_node *node)
197 return gen_binop(node, get_Add_left(node), get_Add_right(node),
201 static ir_node *gen_Or(ir_node *node)
203 return gen_binop(node, get_Add_left(node), get_Add_right(node),
207 static ir_node *gen_Eor(ir_node *node)
209 return gen_binop(node, get_Add_left(node), get_Add_right(node),
213 static ir_node *gen_Shl(ir_node *node)
215 return gen_binop(node, get_Add_left(node), get_Add_right(node),
219 static ir_node *gen_Shr(ir_node *node)
221 return gen_binop(node, get_Add_left(node), get_Add_right(node),
225 static ir_node *gen_Shrs(ir_node *node)
227 return gen_binop(node, get_Add_left(node), get_Add_right(node),
231 static ir_node *gen_Not(ir_node *node)
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);
241 /* we can transform not->or to nor */
243 return gen_binop(op, get_Or_left(op), get_Or_right(op),
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);
255 static ir_node *gen_Minus(ir_node *node)
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);
265 /* construct (0 - op) */
266 zero = mips_create_zero();
267 res = new_rd_mips_subu(dbgi, irg, block, zero, new_op);
272 static ir_node *gen_Abs(ir_node *node)
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;
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);
291 static ir_node* gen_Const(ir_node *node)
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);
300 unsigned long val, lower, upper;
302 if(tarval_is_long(tv)) {
303 val = get_tarval_long(tv);
305 panic("Can't get value of tarval %+F", node);
308 val = get_tarval_long(tv);
310 lower = val & 0xffff;
311 upper = (val >> 16) & 0xffff;
313 upper_node = mips_create_zero();
315 upper_node = new_rd_mips_lui(dbgi, irg, block, MIPS_IMM_CONST, NULL,
322 or_const = mips_create_Immediate(lower);
323 lower_node = new_rd_mips_or(dbgi, irg, block, upper_node, or_const);
328 static ir_node* gen_SymConst(ir_node *node)
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));
334 const arch_register_t **slots;
335 ir_node *lui, *or_const, *or;
337 if(get_SymConst_kind(node) != symconst_addr_ent) {
338 panic("Only address entity symconsts supported in mips backend");
341 entity = get_SymConst_entity(node);
343 lui = new_rd_mips_lui(dbgi, irg, block, MIPS_IMM_SYMCONST_HI,
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);
349 slots = get_mips_slots(or_const);
350 slots[0] = &mips_gp_regs[REG_GP_NOREG];
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);
360 * Generates a mips node for a firm Load node
362 static ir_node *gen_Load(ir_node *node)
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);
376 ASSERT_NO_FLOAT(mode);
377 assert(mode_needs_gp_reg(mode));
379 /* TODO: make use of offset in ptrs */
381 switch(get_mode_size_bits(mode)) {
383 func = new_rd_mips_lw;
386 func = sign ? new_rd_mips_lh : new_rd_mips_lhu;
389 func = sign ? new_rd_mips_lb : new_rd_mips_lbu;
392 panic("mips backend only support 32, 16, 8 bit loads");
395 res = func(dbgi, irg, block, new_ptr, new_mem, NULL, 0);
396 set_irn_pinned(res, get_irn_pinned(node));
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);
406 * Generates a mips node for a firm Store node
408 static ir_node *gen_Store(ir_node *node)
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);
423 assert(mode_needs_gp_reg(mode));
425 switch(get_mode_size_bits(mode)) {
427 func = new_rd_mips_sw;
430 func = new_rd_mips_sh;
433 func = new_rd_mips_sb;
436 panic("store only supported for 32, 16, 8 bit values in mips backend");
439 res = func(dbgi, irg, block, new_ptr, new_val, new_mem, NULL, 0);
440 set_irn_pinned(res, get_irn_pinned(node));
445 static ir_node *gen_Proj_DivMod(ir_node *node)
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);
455 assert(is_mips_div(new_div) || is_mips_divu(new_div));
457 switch(get_irn_opcode(divmod)) {
461 return new_rd_Proj(dbgi, irg, block, new_div, mode_M,
464 proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
466 return new_rd_mips_mflo(dbgi, irg, block, proj);
473 return new_rd_Proj(dbgi, irg, block, new_div, mode_M,
476 proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
478 return new_rd_mips_mfhi(dbgi, irg, block, proj);
486 return new_rd_Proj(dbgi, irg, block, new_div, mode_M,
488 case pn_DivMod_res_div:
489 proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
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,
495 return new_rd_mips_mfhi(dbgi, irg, block, proj);
503 panic("invalid proj attached to %+F", divmod);
506 static ir_node *gen_Proj_Start(ir_node *node)
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);
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);
518 if(node == get_irg_anchor(irg, anchor_tls)) {
520 return be_duplicate_node(node);
522 return be_duplicate_node(node);
525 static ir_node *gen_Proj(ir_node *node)
527 ir_graph *irg = current_ir_graph;
528 dbg_info *dbgi = get_irn_dbg_info(node);
529 ir_node *pred = get_Proj_pred(node);
531 switch(get_irn_opcode(pred)) {
539 return gen_Proj_DivMod(node);
542 return gen_Proj_Start(node);
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);
551 return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn);
556 return be_duplicate_node(node);
559 static ir_node *gen_Phi(ir_node *node)
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);
567 if(mode_needs_gp_reg(mode)) {
568 assert(get_mode_size_bits(mode) <= 32);
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);
579 be_enqueue_preds(node);
586 ir_node *gen_node_for_SwitchCond(mips_transform_env_t *env)
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;
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;
603 // mode_b conds are handled by gen_node_for_Proj
604 if(get_mode_sort(selector_mode) != irms_int_number)
607 assert(get_mode_size_bits(selector_mode) == 32);
610 defaultprojn = get_Cond_defaultProj(node);
612 // go over all projs to find min-&maxval of the switch
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");
619 pn = get_Proj_proj(proj);
620 if(pn == defaultprojn) {
630 assert(defaultproj != NULL);
632 // subtract minval from the switch value
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);
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));
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);
652 zero = gen_zero_node(env, dbg, irg, block);
653 beq = new_rd_mips_beq(dbg, irg, block, sltu, zero, mode_T);
655 // attach defaultproj to beq now
656 set_irn_n(defaultproj, 0, beq);
657 set_Proj_proj(defaultproj, 1);
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);
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);
670 proj = new_rd_Proj(dbg, irg, block, load, mode_Iu, pn_Load_res);
672 switchjmp = new_rd_mips_SwitchJump(dbg, irg, block, proj, mode_T);
673 attr = get_mips_attr(switchjmp);
674 attr->switch_default_pn = defaultprojn;
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));
680 attr = get_mips_attr(la);
681 attr->symconst_id = new_id_from_str(mips_get_jumptbl_label(switchjmp));
687 static ir_node *gen_Cond(ir_node *node)
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);
703 /* TODO: use blez & co. when possible */
709 panic("mips backend can't handle unoptimized constant Cond");
712 res = new_rd_mips_beq(dbgi, irg, block, new_left, new_right);
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);
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);
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);
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);
740 res = new_rd_mips_bne(dbgi, irg, block, new_left, new_right);
744 panic("mips backend doesn't handle unordered compares yet");
750 static ir_node *gen_Conv(ir_node *node)
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);
763 assert(mode_needs_gp_reg(src_mode));
764 assert(mode_needs_gp_reg(dst_mode));
766 /* we only need to do something on upconvs */
767 if(src_size >= dst_size) {
768 /* unnecessary conv */
772 if(mode_is_signed(src_mode)) {
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);
778 panic("invalid conv %+F", node);
784 and_const = mips_create_Immediate(0xff);
785 } else if(src_size == 16) {
786 and_const = mips_create_Immediate(0xffff);
788 panic("invalid conv %+F", node);
790 res = new_rd_mips_and(dbgi, irg, block, new_op, and_const);
796 static ir_node *create_div(ir_node *node, ir_node *left, ir_node *right,
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);
806 if(mode_is_signed(mode)) {
807 res = new_rd_mips_div(dbgi, irg, block, new_left, new_right);
809 res = new_rd_mips_divu(dbgi, irg, block, new_left, new_right);
812 set_irn_pinned(res, get_irn_pinned(node));
817 static ir_node *gen_DivMod(ir_node *node)
819 return create_div(node, get_DivMod_left(node), get_DivMod_right(node),
820 get_DivMod_resmode(node));
823 static ir_node *gen_Div(ir_node *node)
825 return create_div(node, get_Div_left(node), get_Div_right(node),
826 get_Div_resmode(node));
829 static ir_node *gen_Mod(ir_node *node)
831 return create_div(node, get_Mod_left(node), get_Mod_right(node),
832 get_Mod_resmode(node));
836 static ir_node *gen_node_for_Mul(mips_transform_env_t *env) {
837 ir_node *node = env->irn;
841 ir_mode *mode = get_irn_mode(node);
843 op1 = get_Mul_left(node);
844 op2 = get_Mul_right(node);
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));
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));
853 mul = new_rd_mips_multu(env->dbg, env->irg, env->block, get_Mul_left(node), get_Mul_right(node));
855 mflo = new_rd_mips_mflo(env->dbg, env->irg, env->block, mul);
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);
868 return new_rd_mips_jr(dbg, irg, block, target);
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;
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);
885 static ir_node *gen_Unknown(ir_node *node)
888 assert(mode_needs_gp_reg(get_irn_mode(node)));
889 return mips_create_zero();
894 * lower a copyB into standard Firm assembler :-)
896 ir_node *gen_code_for_CopyB(ir_node *block, ir_node *node) {
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);
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);
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);
916 /* build the control loop */
917 in[0] = in[1] = new_r_Unknown(irg, mode_X);
919 new_bl = new_r_Block(irg, 2, in);
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);
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);
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);
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);
935 jmp = get_Block_cfgpred(block, 0);
936 set_Block_cfgpred(block, 0, projF);
938 set_Block_cfgpred(new_bl, 0, jmp);
939 set_Block_cfgpred(new_bl, 1, projT);
945 in[1] = new_r_Unknown(irg, p_mode);
946 src_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
949 dst_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
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);
957 in[1] = new_r_Unknown(irg, mode_M);
958 mem_phi = new_r_Phi(irg, new_bl, 2, in, mode_M);
963 /* create 4 parallel loads */
964 for (i = 0; i < 4; ++i) {
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);
972 ld[i] = new_rd_Proj(dbg, irg, new_bl, load, mode_Iu, pn_Load_res);
975 /* create 4 parallel stores */
976 for (i = 0; i < 4; ++i) {
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);
984 mm[i] = new_rd_Proj(dbg, irg, new_bl, store, mode_M, pn_Store_M);
986 mem = new_r_Sync(irg, new_bl, 4, mm);
988 set_Phi_pred(mem_phi, 1, mem);
991 // output store/loads manually
993 for(i = size; i > 0; ) {
995 ir_node *load, *store, *projv;
996 int offset = size - i;
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);
1013 projv = new_rd_Proj(dbg, irg, block, load, mode, pn_Load_res);
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);
1020 mm[n] = new_rd_Proj(dbg, irg, block, store, mode_M, pn_Store_M);
1025 result = new_r_Sync(irg, block, n, mm);
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);
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);
1047 static void mips_transform_Spill(mips_transform_env_t* env) {
1048 ir_node *node = env->irn;
1049 ir_node *sched_point = NULL;
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);
1056 if(sched_is_scheduled(node)) {
1057 sched_point = sched_prev(node);
1060 store = new_rd_mips_sw(env->dbg, env->irg, env->block, ptr, val, nomem,
1064 sched_add_after(sched_point, store);
1068 exchange(node, store);
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;
1080 if(sched_is_scheduled(node)) {
1081 sched_point = sched_prev(node);
1084 load = new_rd_mips_lw(env->dbg, env->irg, env->block, ptr, mem, ent, 0);
1086 proj = new_rd_Proj(env->dbg, env->irg, env->block, load, mode_Iu, pn_mips_lw_res);
1089 sched_add_after(sched_point, load);
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);
1098 exchange(node, proj);
1102 static ir_node *gen_AddSP(ir_node *node)
1104 ir_node *node = env->irn;
1107 const arch_register_t *reg;
1109 op1 = get_irn_n(node, 0);
1110 op2 = get_irn_n(node, 1);
1112 add = new_rd_mips_addu(env->dbg, env->irg, env->block, op1, op2);
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);
1122 /*********************************************************
1125 * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
1126 * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
1127 * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
1128 * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
1130 *********************************************************/
1132 typedef ir_node *(*mips_transform_func) (ir_node *node);
1134 static void register_transformer(ir_op *op, mips_transform_func func)
1136 assert(op->ops.generic == NULL);
1137 op->ops.generic = (op_func) func;
1140 static void register_transformers(void)
1142 clear_irp_opcodes_generic_func();
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);
1169 void mips_transform_graph(mips_code_gen_t *cg)
1171 register_transformers();
1172 be_transform_graph(cg->birg, NULL);
1176 * Calls the transform functions for Spill and Reload.
1178 void mips_after_ra_walker(ir_node *node, void *env) {
1179 mips_code_gen_t *cg = env;
1180 mips_transform_env_t tenv;
1185 tenv.block = get_nodes_block(node);
1186 tenv.dbg = get_irn_dbg_info(node);
1187 tenv.irg = current_ir_graph;
1189 tenv.mode = get_irn_mode(node);
1192 if (be_is_Reload(node)) {
1193 mips_transform_Reload(&tenv);
1194 } else if (be_is_Spill(node)) {
1195 mips_transform_Spill(&tenv);