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
31 #include "irgraph_t.h"
43 #include "../benode.h"
45 #include "../besched.h"
46 #include "../besched.h"
48 #include "../betranshlp.h"
49 #include "bearch_mips_t.h"
51 #include "mips_nodes_attr.h"
52 #include "mips_transform.h"
53 #include "mips_new_nodes.h"
54 #include "mips_map_regs.h"
55 #include "mips_util.h"
56 #include "mips_emitter.h"
58 #include "gen_mips_regalloc_if.h"
60 /****************************************************************************************************
62 * | | | | / _| | | (_)
63 * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
64 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
65 * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
66 * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
68 ****************************************************************************************************/
70 typedef ir_node *construct_binop_func(dbg_info *db, ir_node *block,
71 ir_node *left, ir_node *right);
73 static inline int mode_needs_gp_reg(ir_mode *mode)
75 return mode_is_int(mode) || mode_is_reference(mode);
78 ir_node *mips_create_Immediate(long val)
80 ir_graph *irg = current_ir_graph;
81 ir_node *block = get_irg_start_block(irg);
84 assert(val >= -32768 && val <= 32767);
85 res = new_bd_mips_Immediate(NULL, block, MIPS_IMM_CONST, NULL, val);
86 arch_set_irn_register(res, &mips_gp_regs[REG_GP_NOREG]);
91 ir_node* mips_create_zero(void)
93 ir_graph *irg = current_ir_graph;
94 ir_node *block = get_irg_start_block(irg);
95 ir_node *zero = new_bd_mips_zero(NULL, block);
97 arch_set_irn_register(zero, &mips_gp_regs[REG_GP_NOREG]);
102 static ir_node *try_create_Immediate(ir_node *node)
111 mode = get_irn_mode(node);
112 if (!mode_needs_gp_reg(mode))
115 tv = get_Const_tarval(node);
116 if (tarval_is_long(tv)) {
117 val = get_tarval_long(tv);
119 ir_fprintf(stderr, "Optimisation Warning: tarval %+F is not a long?\n",
124 if (val < -32768 || val > 32767)
127 return mips_create_Immediate(val);
130 static void create_binop_operands(ir_node **new_left, ir_node **new_right,
131 ir_node *left, ir_node *right,
134 *new_right = try_create_Immediate(right);
135 if (*new_right != NULL) {
136 *new_left = be_transform_node(left);
139 if (is_commutative) {
140 *new_right = try_create_Immediate(left);
141 if (*new_right != NULL) {
142 *new_left = be_transform_node(right);
147 *new_left = be_transform_node(left);
148 *new_right = be_transform_node(right);
151 static ir_node *gen_binop(ir_node *node, ir_node *left, ir_node *right,
152 construct_binop_func func, int supports_immediate)
154 dbg_info *dbgi = get_irn_dbg_info(node);
155 ir_node *block = be_transform_node(get_nodes_block(node));
157 ir_node *new_left, *new_right;
159 assert(mode_needs_gp_reg(get_irn_mode(node)));
161 if (supports_immediate) {
162 int is_commutative = is_op_commutative(get_irn_op(node));
163 create_binop_operands(&new_left, &new_right, left, right,
166 new_left = be_transform_node(left);
167 new_right = be_transform_node(right);
170 res = func(dbgi, block, new_left, new_right);
175 static ir_node *gen_Add(ir_node *node)
177 /* TODO: match add(symconst, const) */
178 return gen_binop(node, get_Add_left(node), get_Add_right(node),
179 new_bd_mips_addu, 1);
182 static ir_node *gen_Sub(ir_node *node)
184 return gen_binop(node, get_Sub_left(node), get_Sub_right(node),
185 new_bd_mips_addu, 0);
188 static ir_node *gen_And(ir_node *node)
190 return gen_binop(node, get_Add_left(node), get_Add_right(node),
194 static ir_node *gen_Or(ir_node *node)
196 return gen_binop(node, get_Add_left(node), get_Add_right(node),
200 static ir_node *gen_Eor(ir_node *node)
202 return gen_binop(node, get_Add_left(node), get_Add_right(node),
206 static ir_node *gen_Shl(ir_node *node)
208 return gen_binop(node, get_Add_left(node), get_Add_right(node),
212 static ir_node *gen_Shr(ir_node *node)
214 return gen_binop(node, get_Add_left(node), get_Add_right(node),
218 static ir_node *gen_Shrs(ir_node *node)
220 return gen_binop(node, get_Add_left(node), get_Add_right(node),
224 static ir_node *gen_Not(ir_node *node)
226 dbg_info *dbgi = get_irn_dbg_info(node);
227 ir_node *block = be_transform_node(get_nodes_block(node));
228 ir_node *op = get_Not_op(node);
233 /* we can transform not->or to nor */
235 return gen_binop(op, get_Or_left(op), get_Or_right(op),
239 /* construct (op < 1) */
240 one = mips_create_Immediate(1);
241 new_op = be_transform_node(op);
242 res = new_bd_mips_sltu(dbgi, block, new_op, one);
247 static ir_node *gen_Minus(ir_node *node)
249 dbg_info *dbgi = get_irn_dbg_info(node);
250 ir_node *block = be_transform_node(get_nodes_block(node));
251 ir_node *op = get_Minus_op(node);
252 ir_node *new_op = be_transform_node(op);
256 /* construct (0 - op) */
257 zero = mips_create_zero();
258 res = new_bd_mips_subu(dbgi, block, zero, new_op);
263 static ir_node *gen_Abs(ir_node *node)
265 dbg_info *dbgi = get_irn_dbg_info(node);
266 ir_node *block = be_transform_node(get_nodes_block(node));
267 ir_node *op = get_Abs_op(node);
268 ir_node *new_op = be_transform_node(op);
269 ir_node *sra_const, *sra, *add, *xor;
271 /* TODO: support other bit sizes... */
272 assert(get_mode_size_bits(get_irn_mode(node)) == 32);
273 sra_const = mips_create_Immediate(31);
274 sra = new_bd_mips_sra( dbgi, block, new_op, sra_const);
275 add = new_bd_mips_addu(dbgi, block, new_op, sra);
276 xor = new_bd_mips_xor( dbgi, block, sra, add);
281 static ir_node* gen_Const(ir_node *node)
283 dbg_info *dbgi = get_irn_dbg_info(node);
284 ir_node *block = be_transform_node(get_nodes_block(node));
285 tarval *tv = get_Const_tarval(node);
289 unsigned long val, lower, upper;
291 if (tarval_is_long(tv)) {
292 val = get_tarval_long(tv);
294 panic("Can't get value of tarval %+F", node);
297 val = get_tarval_long(tv);
299 lower = val & 0xffff;
300 upper = (val >> 16) & 0xffff;
302 upper_node = mips_create_zero();
304 upper_node = new_bd_mips_lui(dbgi, block, MIPS_IMM_CONST, NULL, upper);
310 or_const = mips_create_Immediate(lower);
311 lower_node = new_bd_mips_or(dbgi, block, upper_node, or_const);
316 static ir_node* gen_SymConst(ir_node *node)
318 dbg_info *dbgi = get_irn_dbg_info(node);
319 ir_node *block = be_transform_node(get_nodes_block(node));
321 ir_node *lui, *or_const, *or;
323 if (get_SymConst_kind(node) != symconst_addr_ent) {
324 panic("Only address entity symconsts supported in mips backend");
327 entity = get_SymConst_entity(node);
329 lui = new_bd_mips_lui(dbgi, block, MIPS_IMM_SYMCONST_HI, entity, 0);
330 or_const = new_bd_mips_Immediate(dbgi, block, MIPS_IMM_SYMCONST_LO, entity, 0);
331 or = new_bd_mips_or(dbgi, block, lui, or_const);
333 arch_set_irn_register(or_const, &mips_gp_regs[REG_GP_NOREG]);
338 typedef ir_node* (*gen_load_func)(dbg_info *dbg, ir_node *block, ir_node *ptr,
339 ir_node *mem, ir_entity *entity, long offset);
342 * Generates a mips node for a firm Load node
344 static ir_node *gen_Load(ir_node *node)
346 dbg_info *dbgi = get_irn_dbg_info(node);
347 ir_node *block = be_transform_node(get_nodes_block(node));
348 ir_node *mem = get_Load_mem(node);
349 ir_node *new_mem = be_transform_node(mem);
350 ir_node *ptr = get_Load_ptr(node);
351 ir_node *new_ptr = be_transform_node(ptr);
352 ir_mode *mode = get_Load_mode(node);
353 int sign = get_mode_sign(mode);
357 ASSERT_NO_FLOAT(mode);
358 assert(mode_needs_gp_reg(mode));
360 /* TODO: make use of offset in ptrs */
362 switch (get_mode_size_bits(mode)) {
364 func = new_bd_mips_lw;
367 func = sign ? new_bd_mips_lh : new_bd_mips_lhu;
370 func = sign ? new_bd_mips_lb : new_bd_mips_lbu;
373 panic("mips backend only support 32, 16, 8 bit loads");
376 res = func(dbgi, block, new_ptr, new_mem, NULL, 0);
377 set_irn_pinned(res, get_irn_pinned(node));
382 typedef ir_node* (*gen_store_func)(dbg_info *dbg, ir_node *block, ir_node *ptr,
383 ir_node *val, ir_node *mem, ir_entity *ent, long offset);
386 * Generates a mips node for a firm Store node
388 static ir_node *gen_Store(ir_node *node)
390 dbg_info *dbgi = get_irn_dbg_info(node);
391 ir_node *block = be_transform_node(get_nodes_block(node));
392 ir_node *mem = get_Store_mem(node);
393 ir_node *new_mem = be_transform_node(mem);
394 ir_node *ptr = get_Store_ptr(node);
395 ir_node *new_ptr = be_transform_node(ptr);
396 ir_node *val = get_Store_value(node);
397 ir_node *new_val = be_transform_node(val);
398 ir_mode *mode = get_irn_mode(val);
402 assert(mode_needs_gp_reg(mode));
404 switch (get_mode_size_bits(mode)) {
406 func = new_bd_mips_sw;
409 func = new_bd_mips_sh;
412 func = new_bd_mips_sb;
415 panic("store only supported for 32, 16, 8 bit values in mips backend");
418 res = func(dbgi, block, new_ptr, new_val, new_mem, NULL, 0);
419 set_irn_pinned(res, get_irn_pinned(node));
424 static ir_node *gen_Proj_DivMod(ir_node *node)
426 dbg_info *dbgi = get_irn_dbg_info(node);
427 ir_node *block = be_transform_node(get_nodes_block(node));
428 ir_node *divmod = get_Proj_pred(node);
429 ir_node *new_div = be_transform_node(divmod);
430 long pn = get_Proj_proj(node);
433 assert(is_mips_div(new_div) || is_mips_divu(new_div));
435 switch (get_irn_opcode(divmod)) {
439 return new_rd_Proj(dbgi, block, new_div, mode_M, pn_mips_div_M);
441 proj = new_rd_Proj(dbgi, block, new_div, mode_M, pn_mips_div_lohi);
442 return new_bd_mips_mflo(dbgi, block, proj);
449 return new_rd_Proj(dbgi, block, new_div, mode_M, pn_mips_div_M);
451 proj = new_rd_Proj(dbgi, block, new_div, mode_M, pn_mips_div_lohi);
452 return new_bd_mips_mfhi(dbgi, block, proj);
460 return new_rd_Proj(dbgi, block, new_div, mode_M, pn_mips_div_M);
461 case pn_DivMod_res_div:
462 proj = new_rd_Proj(dbgi, block, new_div, mode_M, pn_mips_div_lohi);
463 return new_bd_mips_mflo(dbgi, block, proj);
464 case pn_DivMod_res_mod:
465 proj = new_rd_Proj(dbgi, block, new_div, mode_M, pn_mips_div_lohi);
466 return new_bd_mips_mfhi(dbgi, block, proj);
474 panic("invalid proj attached to %+F", divmod);
477 static ir_node *gen_Proj_Start(ir_node *node)
479 dbg_info *dbgi = get_irn_dbg_info(node);
480 ir_node *block = be_transform_node(get_nodes_block(node));
481 long pn = get_Proj_proj(node);
484 if (pn == pn_Start_X_initial_exec) {
485 /* we exchange the projx with a jump */
486 ir_node *jump = new_rd_Jmp(dbgi, block);
489 irg = get_irn_irg(node);
490 if (node == get_irg_anchor(irg, anchor_tls)) {
492 return be_duplicate_node(node);
494 return be_duplicate_node(node);
497 static ir_node *gen_Proj(ir_node *node)
499 dbg_info *dbgi = get_irn_dbg_info(node);
500 ir_node *pred = get_Proj_pred(node);
502 switch (get_irn_opcode(pred)) {
510 return gen_Proj_DivMod(node);
513 return gen_Proj_Start(node);
516 assert(get_irn_mode(node) != mode_T);
517 if (mode_needs_gp_reg(get_irn_mode(node))) {
518 ir_node *new_pred = be_transform_node(pred);
519 ir_node *block = be_transform_node(get_nodes_block(node));
520 long pn = get_Proj_proj(node);
522 return new_rd_Proj(dbgi, block, new_pred, mode_Iu, pn);
527 return be_duplicate_node(node);
530 static ir_node *gen_Phi(ir_node *node)
532 dbg_info *dbgi = get_irn_dbg_info(node);
533 ir_node *block = be_transform_node(get_nodes_block(node));
534 ir_graph *irg = get_Block_irg(block);
535 ir_mode *mode = get_irn_mode(node);
538 if (mode_needs_gp_reg(mode)) {
539 assert(get_mode_size_bits(mode) <= 32);
543 /* phi nodes allow loops, so we use the old arguments for now
544 * and fix this later */
545 phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node),
546 get_irn_in(node) + 1);
547 copy_node_attr(node, phi);
548 be_duplicate_deps(node, phi);
550 be_enqueue_preds(node);
556 static ir_node *gen_node_for_SwitchCond(mips_transform_env_t *env)
558 ir_node *selector = get_Cond_selector(env->irn);
559 ir_mode *selector_mode = get_irn_mode(selector);
560 ir_node *node = env->irn;
561 dbg_info *dbg = env->dbg;
562 ir_graph *irg = env->irg;
563 ir_node *block = env->block;
564 ir_node *sub, *sltu, *minval_const, *max_const, *switchjmp;
565 ir_node *defaultproj, *defaultproj_succ;
567 long pn, minval, maxval, defaultprojn;
568 const ir_edge_t *edge;
569 ir_node *zero, *two_const, *add, *la, *load, *proj;
570 ir_mode *unsigned_mode;
573 // mode_b conds are handled by gen_node_for_Proj
574 if (get_mode_sort(selector_mode) != irms_int_number)
577 assert(get_mode_size_bits(selector_mode) == 32);
580 defaultprojn = get_Cond_default_proj(node);
582 // go over all projs to find min-&maxval of the switch
585 foreach_out_edge(node, edge) {
586 ir_node* proj = get_edge_src_irn(edge);
587 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
589 pn = get_Proj_proj(proj);
590 if (pn == defaultprojn) {
600 assert(defaultproj != NULL);
602 // subtract minval from the switch value
605 minval_const = new_rd_Const(dbg, irg, selector_mode, new_tarval_from_long(minval, selector_mode));
606 minval_const = gen_node_for_Const(env, dbg, irg, block, minval_const);
607 sub = new_bd_mips_sub(dbg, block, selector, minval_const);
612 // compare if we're above maxval-minval or below zero.
613 // we can do this with 1 compare because we use unsigned mode
614 unsigned_mode = new_ir_mode(get_mode_name(selector_mode),
615 get_mode_sort(selector_mode), get_mode_size_bits(selector_mode),
616 0, get_mode_arithmetic(selector_mode), get_mode_modulo_shift(selector_mode));
618 max_const = new_rd_Const(dbg, irg, unsigned_mode, new_tarval_from_long(maxval - minval + 1, unsigned_mode));
619 max_const = gen_node_for_Const(env, dbg, irg, block, max_const);
620 sltu = new_bd_mips_slt(dbg, block, sub, max_const);
622 zero = gen_zero_node(env, dbg, irg, block);
623 beq = new_bd_mips_beq(dbg, block, sltu, zero, mode_T);
625 // attach defaultproj to beq now
626 set_irn_n(defaultproj, 0, beq);
627 set_Proj_proj(defaultproj, 1);
629 two_const = new_rd_Const(dbg, irg, block, unsigned_mode, new_tarval_from_long(2, unsigned_mode));
630 two_const = gen_node_for_Const(env, dbg, irg, block, two_const);
631 sl = new_bd_mips_sl(dbg, block, sub, two_const);
633 la = new_bd_mips_la( dbg, block);
634 add = new_bd_mips_addu( dbg, block, sl, la);
635 load = new_bd_mips_load_r(dbg, block, new_NoMem(), add, mode_T);
636 attr = get_mips_attr(load);
637 attr->modes.load_store_mode = mode_Iu;
638 attr->tv = new_tarval_from_long(0, mode_Iu);
640 proj = new_rd_Proj(dbg, block, load, mode_Iu, pn_Load_res);
642 switchjmp = new_bd_mips_SwitchJump(dbg, block, proj, mode_T);
643 attr = get_mips_attr(switchjmp);
644 attr->switch_default_pn = defaultprojn;
646 edge = get_irn_out_edge_first(defaultproj);
647 defaultproj_succ = get_edge_src_irn(edge);
648 attr->symconst_id = new_id_from_str(mips_get_block_label(defaultproj_succ));
650 attr = get_mips_attr(la);
651 attr->symconst_id = new_id_from_str(mips_get_jumptbl_label(switchjmp));
657 static ir_node *gen_Cond(ir_node *node)
659 dbg_info *dbgi = get_irn_dbg_info(node);
660 ir_node *block = get_nodes_block(node);
661 ir_node *sel_proj = get_Cond_selector(node);
662 ir_node *cmp = get_Proj_pred(sel_proj);
663 ir_node *left = get_Cmp_left(cmp);
664 ir_node *new_left = be_transform_node(left);
665 ir_node *right = get_Cmp_right(cmp);
666 ir_node *new_right = be_transform_node(right);
667 long pnc = get_Proj_proj(sel_proj);
672 /* TODO: use blez & co. when possible */
678 panic("mips backend can't handle unoptimized constant Cond");
681 res = new_bd_mips_beq(dbgi, block, new_left, new_right);
685 zero = mips_create_zero();
686 slt = new_bd_mips_slt(dbgi, block, new_left, new_right);
687 res = new_bd_mips_bne(dbgi, block, slt, zero);
691 zero = mips_create_zero();
692 slt = new_bd_mips_slt(dbgi, block, new_right, new_left);
693 res = new_bd_mips_beq(dbgi, block, slt, zero);
697 zero = mips_create_zero();
698 slt = new_bd_mips_slt(dbgi, block, new_right, new_left);
699 res = new_bd_mips_bne(dbgi, block, slt, zero);
703 zero = mips_create_zero();
704 slt = new_bd_mips_slt(dbgi, block, new_right, new_left);
705 res = new_bd_mips_bne(dbgi, block, slt, zero);
709 res = new_bd_mips_bne(dbgi, block, new_left, new_right);
713 panic("mips backend doesn't handle unordered compares yet");
719 static ir_node *gen_Conv(ir_node *node)
721 dbg_info *dbgi = get_irn_dbg_info(node);
722 ir_node *block = be_transform_node(get_nodes_block(node));
723 ir_node *op = get_Conv_op(node);
724 ir_node *new_op = be_transform_node(op);
725 ir_mode *src_mode = get_irn_mode(op);
726 ir_mode *dst_mode = get_irn_mode(node);
727 int src_size = get_mode_size_bits(src_mode);
728 int dst_size = get_mode_size_bits(dst_mode);
731 assert(mode_needs_gp_reg(src_mode));
732 assert(mode_needs_gp_reg(dst_mode));
734 /* we only need to do something on upconvs */
735 if (src_size >= dst_size) {
736 /* unnecessary conv */
740 if (mode_is_signed(src_mode)) {
742 res = new_bd_mips_seb(dbgi, block, new_op);
743 } else if (src_size == 16) {
744 res = new_bd_mips_seh(dbgi, block, new_op);
746 panic("invalid conv %+F", node);
752 and_const = mips_create_Immediate(0xff);
753 } else if (src_size == 16) {
754 and_const = mips_create_Immediate(0xffff);
756 panic("invalid conv %+F", node);
758 res = new_bd_mips_and(dbgi, block, new_op, and_const);
764 static ir_node *create_div(ir_node *node, ir_node *left, ir_node *right,
767 dbg_info *dbgi = get_irn_dbg_info(node);
768 ir_node *block = be_transform_node(get_nodes_block(node));
769 ir_node *new_left = be_transform_node(left);
770 ir_node *new_right = be_transform_node(right);
773 if (mode_is_signed(mode)) {
774 res = new_bd_mips_div(dbgi, block, new_left, new_right);
776 res = new_bd_mips_divu(dbgi, block, new_left, new_right);
779 set_irn_pinned(res, get_irn_pinned(node));
784 static ir_node *gen_DivMod(ir_node *node)
786 return create_div(node, get_DivMod_left(node), get_DivMod_right(node),
787 get_DivMod_resmode(node));
790 static ir_node *gen_Div(ir_node *node)
792 return create_div(node, get_Div_left(node), get_Div_right(node),
793 get_Div_resmode(node));
796 static ir_node *gen_Mod(ir_node *node)
798 return create_div(node, get_Mod_left(node), get_Mod_right(node),
799 get_Mod_resmode(node));
803 static ir_node *gen_node_for_Mul(mips_transform_env_t *env)
805 ir_node *node = env->irn;
809 ir_mode *mode = get_irn_mode(node);
811 op1 = get_Mul_left(node);
812 op2 = get_Mul_right(node);
814 assert(get_mode_size_bits(env->mode) == 32);
815 assert(get_mode_size_bits(get_irn_mode(op1)) == get_mode_size_bits(env->mode));
816 assert(get_mode_size_bits(get_irn_mode(op2)) == get_mode_size_bits(env->mode));
818 if (mode_is_signed(mode)) {
819 mul = new_bd_mips_mult(env->dbg, env->block, get_Mul_left(node), get_Mul_right(node));
821 mul = new_bd_mips_multu(env->dbg, env->block, get_Mul_left(node), get_Mul_right(node));
823 mflo = new_bd_mips_mflo(env->dbg, env->block, mul);
828 static ir_node *gen_node_for_IJmp(mips_transform_env_t *env)
830 ir_node *node = env->irn;
831 dbg_info *dbg = get_irn_dbg_info(node);
832 ir_node *block = get_nodes_block(node);
833 ir_node *target = get_IJmp_target(node);
835 return new_bd_mips_jr(dbg, block, target);
838 static ir_node *gen_node_for_Rot(mips_transform_env_t *env)
840 ir_node *node = env->irn;
841 ir_node *subu, *srlv, *sllv, *or;
843 subu = new_bd_mips_subuzero(env->dbg, env->block, get_Rot_right(node));
844 srlv = new_bd_mips_srlv(env->dbg, env->block, get_Rot_left(node), subu);
845 sllv = new_bd_mips_sllv(env->dbg, env->block, get_Rot_left(node), get_Rot_right(node));
846 or = new_bd_mips_or(env->dbg, env->block, sllv, srlv);
852 static ir_node *gen_Unknown(ir_node *node)
855 assert(mode_needs_gp_reg(get_irn_mode(node)));
856 return mips_create_zero();
861 * lower a copyB into standard Firm assembler :-)
863 ir_node *gen_code_for_CopyB(ir_node *block, ir_node *node)
866 ir_node *dst = get_CopyB_dst(node);
867 ir_node *src = get_CopyB_src(node);
868 ir_type *type = get_CopyB_type(node);
869 ir_node *mem = get_CopyB_mem(node);
871 ir_node *result = NULL;
872 int size = get_type_size_bytes(type);
873 dbg_info *dbg = get_irn_dbg_info(node);
874 ir_graph *irg = get_irn_irg(block);
879 ir_node *phi, *projT, *projF, *cmp, *proj, *cond, *jmp, *in[2];
880 ir_node *new_bl, *src_phi, *dst_phi, *mem_phi, *add;
881 ir_mode *p_mode = get_irn_mode(src);
884 /* build the control loop */
885 in[0] = in[1] = new_r_Unknown(irg, mode_X);
887 new_bl = new_r_Block(irg, 2, in);
889 in[0] = cnt = new_Const_long(mode_Is, (size >> 4));
890 in[1] = new_r_Unknown(irg, mode_Is);
891 phi = new_r_Phi(irg, new_bl, 2, in, mode_Is);
893 sub = new_rd_Sub(dbg, irg, new_bl, phi, new_Const_long(mode_Is, -1), mode_Is);
894 set_Phi_pred(phi, 1, sub);
896 cmp = new_rd_Cmp(dbg, irg, new_bl, sub, new_Const_long(mode_Is, 0));
897 proj = new_r_Proj(irg, new_bl, cmp, mode_b, pn_Cmp_Lg);
898 cond = new_rd_Cond(dbg, irg, new_bl, proj);
900 projT = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_true);
901 projF = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_false);
903 jmp = get_Block_cfgpred(block, 0);
904 set_Block_cfgpred(block, 0, projF);
906 set_Block_cfgpred(new_bl, 0, jmp);
907 set_Block_cfgpred(new_bl, 1, projT);
913 in[1] = new_r_Unknown(irg, p_mode);
914 src_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
917 dst_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
919 add = new_rd_Add(dbg, irg, new_bl, src_phi, new_Const_long(mode_Is, 16), p_mode);
920 set_Phi_pred(src_phi, 1, add);
921 add = new_rd_Add(dbg, irg, new_bl, dst_phi, new_Const_long(mode_Is, 16), p_mode);
922 set_Phi_pred(dst_phi, 1, add);
925 in[1] = new_r_Unknown(irg, mode_M);
926 mem_phi = new_r_Phi(irg, new_bl, 2, in, mode_M);
931 /* create 4 parallel loads */
932 for (i = 0; i < 4; ++i) {
935 load = new_bd_mips_load_r(dbg, new_bl, mem_phi, src, mode_T);
936 attr = get_mips_attr(load);
937 attr->modes.load_store_mode = mode_Iu;
938 attr->tv = new_tarval_from_long(i * 4, mode_Iu);
940 ld[i] = new_rd_Proj(dbg, irg, new_bl, load, mode_Iu, pn_Load_res);
943 /* create 4 parallel stores */
944 for (i = 0; i < 4; ++i) {
947 store = new_bd_mips_store_r(dbg, new_bl, mem_phi, dst, ld[i], mode_T);
948 attr = get_mips_attr(store);
949 attr->modes.load_store_mode = mode_Iu;
950 attr->tv = new_tarval_from_long(i * 4, mode_Iu);
952 mm[i] = new_rd_Proj(dbg, irg, new_bl, store, mode_M, pn_Store_M);
954 mem = new_r_Sync(irg, new_bl, 4, mm);
956 set_Phi_pred(mem_phi, 1, mem);
959 // output store/loads manually
961 for (i = size; i > 0; ) {
963 ir_node *load, *store, *projv;
964 int offset = size - i;
976 load = new_bd_mips_load_r(dbg, block, mem, src, mode_T);
977 attr = get_mips_attr(load);
978 attr->modes.load_store_mode = mode;
979 attr->tv = new_tarval_from_long(offset, mode_Iu);
981 projv = new_rd_Proj(dbg, irg, block, load, mode, pn_Load_res);
983 store = new_bd_mips_store_r(dbg, block, mem, dst, projv, mode_T);
984 attr = get_mips_attr(store);
985 attr->modes.load_store_mode = mode;
986 attr->tv = new_tarval_from_long(offset, mode_Iu);
988 mm[n] = new_rd_Proj(dbg, irg, block, store, mode_M, pn_Store_M);
993 result = new_r_Sync(irg, block, n, mm);
1001 static void mips_fix_CopyB_Proj(mips_transform_env_t* env)
1003 ir_node *node = env->irn;
1004 long n = get_Proj_proj(node);
1006 if (n == pn_CopyB_M_except) {
1007 panic("Unsupported Proj from CopyB");
1008 } else if (n == pn_CopyB_M_regular) {
1009 set_Proj_proj(node, pn_Store_M);
1010 } else if (n == pn_CopyB_M_except) {
1011 set_Proj_proj(node, pn_Store_X_except);
1016 static void mips_transform_Spill(mips_transform_env_t* env)
1018 ir_node *node = env->irn;
1019 ir_node *sched_point = NULL;
1021 ir_node *nomem = new_NoMem();
1022 ir_node *ptr = get_irn_n(node, 0);
1023 ir_node *val = get_irn_n(node, 1);
1024 ir_entity *ent = be_get_frame_entity(node);
1026 if (sched_is_scheduled(node)) {
1027 sched_point = sched_prev(node);
1030 store = new_bd_mips_sw(env->dbg, env->block, ptr, val, nomem, ent, 0);
1033 sched_add_after(sched_point, store);
1037 exchange(node, store);
1040 static void mips_transform_Reload(mips_transform_env_t* env)
1042 ir_node *node = env->irn;
1043 ir_node *sched_point = NULL;
1044 ir_node *load, *proj;
1045 ir_node *ptr = get_irn_n(node, 0);
1046 ir_node *mem = get_irn_n(node, 1);
1047 ir_entity *ent = be_get_frame_entity(node);
1048 const arch_register_t* reg;
1050 if (sched_is_scheduled(node)) {
1051 sched_point = sched_prev(node);
1054 load = new_bd_mips_lw(env->dbg, env->block, ptr, mem, ent, 0);
1056 proj = new_rd_Proj(env->dbg, env->block, load, mode_Iu, pn_mips_lw_res);
1059 sched_add_after(sched_point, load);
1064 /* copy the register from the old node to the new Load */
1065 reg = arch_get_irn_register(node);
1066 arch_set_irn_register(proj, reg);
1068 exchange(node, proj);
1072 static ir_node *gen_AddSP(ir_node *node)
1074 ir_node *node = env->irn;
1077 const arch_register_t *reg;
1079 op1 = get_irn_n(node, 0);
1080 op2 = get_irn_n(node, 1);
1082 add = new_bd_mips_addu(env->dbg, env->block, op1, op2);
1084 /* copy the register requirements from the old node to the new node */
1085 reg = arch_get_irn_register(node);
1086 arch_set_irn_register(add, reg);
1092 /*********************************************************
1095 * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
1096 * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
1097 * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
1098 * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
1100 *********************************************************/
1102 typedef ir_node *(*mips_transform_func) (ir_node *node);
1104 static void register_transformer(ir_op *op, mips_transform_func func)
1106 assert(op->ops.generic == NULL);
1107 op->ops.generic = (op_func) func;
1110 static void register_transformers(void)
1112 clear_irp_opcodes_generic_func();
1114 register_transformer(op_Add, gen_Add);
1115 register_transformer(op_Sub, gen_Sub);
1116 register_transformer(op_And, gen_And);
1117 register_transformer(op_Or, gen_Or);
1118 register_transformer(op_Eor, gen_Eor);
1119 register_transformer(op_Shl, gen_Shl);
1120 register_transformer(op_Shr, gen_Shr);
1121 register_transformer(op_Shrs, gen_Shrs);
1122 register_transformer(op_Not, gen_Not);
1123 register_transformer(op_Minus, gen_Minus);
1124 register_transformer(op_Div, gen_Div);
1125 register_transformer(op_Mod, gen_Mod);
1126 register_transformer(op_DivMod, gen_DivMod);
1127 register_transformer(op_Abs, gen_Abs);
1128 register_transformer(op_Load, gen_Load);
1129 register_transformer(op_Store, gen_Store);
1130 register_transformer(op_Cond, gen_Cond);
1131 register_transformer(op_Conv, gen_Conv);
1132 register_transformer(op_Const, gen_Const);
1133 register_transformer(op_SymConst, gen_SymConst);
1134 register_transformer(op_Unknown, gen_Unknown);
1135 register_transformer(op_Proj, gen_Proj);
1136 register_transformer(op_Phi, gen_Phi);
1139 void mips_transform_graph(mips_code_gen_t *cg)
1141 register_transformers();
1142 be_transform_graph(cg->birg, NULL);
1146 * Calls the transform functions for Spill and Reload.
1148 void mips_after_ra_walker(ir_node *node, void *env)
1150 mips_code_gen_t *cg = env;
1151 mips_transform_env_t tenv;
1156 tenv.block = get_nodes_block(node);
1157 tenv.dbg = get_irn_dbg_info(node);
1158 tenv.irg = current_ir_graph;
1160 tenv.mode = get_irn_mode(node);
1163 if (be_is_Reload(node)) {
1164 mips_transform_Reload(&tenv);
1165 } else if (be_is_Spill(node)) {
1166 mips_transform_Spill(&tenv);