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"
44 #include "../benode_t.h"
46 #include "../besched.h"
47 #include "../besched_t.h"
48 #include "../beirg_t.h"
49 #include "bearch_mips_t.h"
51 #include "mips_nodes_attr.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"
59 #include "gen_mips_regalloc_if.h"
61 /****************************************************************************************************
63 * | | | | / _| | | (_)
64 * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
65 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
66 * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
67 * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
69 ****************************************************************************************************/
71 #define MIPS_GENBINFUNC(mips_nodetype) \
72 static ir_node* mips_gen_##mips_nodetype(mips_transform_env_t *env, ir_node *op1, ir_node *op2) {\
73 ASSERT_NO_FLOAT(env->mode); \
74 /*assert(get_irn_mode(op1) == get_irn_mode(op2));*/ \
75 /*assert(get_irn_mode(op1) == env->mode);*/ \
76 assert(get_mode_size_bits(env->mode) == 32); \
77 return new_rd_mips_##mips_nodetype(env->dbg, env->irg, env->block, op1, op2); \
89 #define MIPS_GENUNFUNC(mips_nodetype) \
90 static ir_node *mips_gen_##mips_nodetype(mips_transform_env_t *env, ir_node *op) { \
91 ASSERT_NO_FLOAT(env->mode); \
92 assert(get_irn_mode(op) == env->mode); \
93 assert(get_mode_size_bits(env->mode) == 32); \
94 return new_rd_mips_##mips_nodetype(env->dbg, env->irg, env->block, op); \
100 ir_node* gen_zero(mips_transform_env_t *env)
102 ir_graph *irg = env->irg;
103 ir_node *block = get_irg_start_block(irg);
104 ir_node *zero = new_rd_mips_zero(NULL, irg, block);
106 arch_set_irn_register(env->cg->arch_env, zero, &mips_gp_regs[REG_ZERO]);
112 ir_node* gen_node_for_Const(mips_transform_env_t *env, dbg_info *dbg, ir_graph *irg, ir_node *block, ir_node *constant)
114 tarval* tv = get_Const_tarval(constant);
118 ir_mode* mode = get_irn_mode(constant);
119 unsigned long val, lower, upper;
121 val = get_tarval_long(tv);
123 lower = val & 0xffff;
124 upper = (val >> 16) & 0xffff;
126 upper_node = gen_zero(env);
128 upper_node = new_rd_mips_lui(dbg, irg, block);
129 attr = get_mips_attr(upper_node);
130 attr->tv = new_tarval_from_long(val, mode);
136 lower_node = new_rd_mips_ori(dbg, irg, block, upper_node);
137 attr = get_mips_attr(lower_node);
138 attr->tv = new_tarval_from_long(lower, mode);
143 static ir_node* exchange_node_for_Const(mips_transform_env_t *env, ir_node* pred, int n) {
144 ir_node *node = env->irn;
145 dbg_info *dbg = get_irn_dbg_info(pred);
146 ir_graph *irg = get_irn_irg(node);
149 if(get_irn_opcode(node) == iro_Phi) {
150 ir_node *phipred = get_nodes_block(node);
151 block = get_Block_cfgpred_block(phipred, n);
153 block = get_nodes_block(node);
156 return gen_node_for_Const(env, dbg, irg, block, pred);
159 static ir_node* gen_node_for_SymConst(mips_transform_env_t *env, ir_node* pred, int n) {
161 ir_node *node = env->irn;
162 dbg_info *dbg = get_irn_dbg_info(pred);
163 ir_graph *irg = get_irn_irg(node);
168 block = get_nodes_block(pred);
170 if(get_SymConst_kind(pred) != symconst_addr_ent) {
171 panic("Only address entity symconsts supported in mips backend");
174 entity = get_SymConst_entity(pred);
176 lui = new_rd_mips_lui(dbg, irg, block);
177 attr = get_mips_attr(lui);
178 attr->symconst = entity;
180 ori = new_rd_mips_ori(dbg, irg, block, lui);
181 attr = get_mips_attr(ori);
182 attr->symconst = entity;
187 typedef ir_node* (*gen_load_func) (dbg_info *dbg, ir_graph *irg,
188 ir_node *block, ir_node *mem, ir_node *ptr);
191 * Generates a mips node for a firm Load node
193 static ir_node *gen_node_for_Load(mips_transform_env_t *env) {
194 ir_graph *irg = env->irg;
195 ir_node *node = env->irn;
196 dbg_info *dbg = get_irn_dbg_info(node);
197 ir_node *block = get_nodes_block(node);
198 ir_node *mem = get_Load_mem(node);
199 ir_node *ptr = get_Load_ptr(node);
200 ir_mode *mode = get_Load_mode(node);
201 int sign = get_mode_sign(mode);
205 ASSERT_NO_FLOAT(get_irn_mode(node));
207 assert(mode->vector_elem == 1);
208 assert(mode->sort == irms_int_number || mode->sort == irms_reference);
210 switch(get_mode_size_bits(mode)) {
212 func = new_rd_mips_lw;
215 func = sign ? new_rd_mips_lh : new_rd_mips_lhu;
218 func = sign ? new_rd_mips_lb : new_rd_mips_lbu;
221 panic("mips backend only support 32, 16, 8 bit loads");
224 result = func(dbg, irg, block, mem, ptr);
228 typedef ir_node* (*gen_store_func) (dbg_info *dbg, ir_graph *irg,
229 ir_node *block, ir_node *mem, ir_node *ptr,
233 * Generates a mips node for a firm Store node
235 static ir_node *gen_node_for_Store(mips_transform_env_t *env) {
236 ir_graph *irg = env->irg;
237 ir_node *node = env->irn;
238 dbg_info *dbg = get_irn_dbg_info(node);
239 ir_node *block = get_nodes_block(node);
240 ir_node *mem = get_Store_mem(node);
241 ir_node *ptr = get_Store_ptr(node);
242 ir_node *val = get_Store_value(node);
243 ir_mode *mode = get_irn_mode(val);
247 ASSERT_NO_FLOAT(mode);
249 assert(mode->vector_elem == 1);
250 assert(mode->sort == irms_int_number || mode->sort == irms_reference);
252 switch(get_mode_size_bits(mode)) {
254 func = new_rd_mips_sw;
257 func = new_rd_mips_sh;
260 func = new_rd_mips_sb;
263 panic("store only supported for 32, 16, 8 bit values in mips backend");
266 result = func(dbg, irg, block, mem, ptr, val);
270 static ir_node *gen_node_for_div_Proj(mips_transform_env_t *env) {
271 ir_node *proj = env->irn;
273 ir_node *pred = get_irn_n(proj, 0);
277 n = get_Proj_proj(proj);
279 // set the div mode to the DivMod node
280 attr = get_mips_attr(pred);
281 assert(attr->original_mode == NULL || attr->original_mode == env->mode);
282 attr->original_mode = env->mode;
284 // we have to construct a new proj here, to avoid circular refs that
285 // happen when we reuse the old one
286 new_proj = new_ir_node(env->dbg, env->irg, env->block, op_Proj, mode_ANY, 1, &pred);
287 set_Proj_proj(new_proj, n);
289 if(n == pn_DivMod_res_div) {
290 return new_rd_mips_mflo(env->dbg, env->irg, env->block, new_proj);
291 } else if(n == pn_DivMod_res_mod) {
292 return new_rd_mips_mfhi(env->dbg, env->irg, env->block, new_proj);
299 ir_node *gen_node_for_Proj(mips_transform_env_t *env)
301 ir_node *proj = env->irn;
302 ir_mode *mode = get_irn_mode(proj);
303 ir_node *predecessor = get_Proj_pred(proj);
305 // all DivMods, Div, Mod should be replaced by now
306 assert(get_irn_opcode(predecessor) != iro_DivMod);
307 assert(get_irn_opcode(predecessor) != iro_Div);
308 assert(get_irn_opcode(predecessor) != iro_Mod);
310 if(is_mips_div(predecessor))
311 return gen_node_for_div_Proj(env);
313 if(is_mips_lw(predecessor) || is_mips_lh(predecessor)
314 || is_mips_lhu(predecessor) || is_mips_lb(predecessor)
315 || is_mips_lbu(predecessor)) {
317 long pn = get_Proj_proj(proj);
318 if(pn == pn_Load_M) {
319 set_Proj_proj(proj, pn_mips_lw_M);
320 } else if(pn == pn_Load_res) {
321 set_Proj_proj(proj, pn_mips_lw_res);
326 if(get_irn_opcode(predecessor) == iro_Cond) {
327 ir_node *selector = get_Cond_selector(predecessor);
328 ir_mode *mode = get_irn_mode(selector);
329 n = get_Proj_proj(proj);
331 if(get_mode_sort(mode) == irms_internal_boolean) {
332 assert(n == pn_Cond_true || n == pn_Cond_false);
333 return gen_node_for_Cond_Proj(env, predecessor, n == pn_Cond_true);
338 if(get_mode_sort(mode) == irms_int_number) {
339 set_irn_mode(proj, mode_Iu);
346 ir_node *gen_node_for_Phi(mips_transform_env_t *env)
348 ir_node *node = env->irn;
349 ir_mode *mode = get_irn_mode(node);
351 if(get_mode_sort(mode) == irms_int_number) {
352 set_irn_mode(node, mode_Iu);
360 ir_node *gen_node_for_SwitchCond(mips_transform_env_t *env)
362 ir_node *selector = get_Cond_selector(env->irn);
363 ir_mode *selector_mode = get_irn_mode(selector);
364 ir_node *node = env->irn;
365 dbg_info *dbg = env->dbg;
366 ir_graph *irg = env->irg;
367 ir_node *block = env->block;
368 ir_node *sub, *sltu, *minval_const, *max_const, *switchjmp;
369 ir_node *defaultproj, *defaultproj_succ;
371 long pn, minval, maxval, defaultprojn;
372 const ir_edge_t *edge;
373 ir_node *zero, *two_const, *add, *la, *load, *proj;
374 ir_mode *unsigned_mode;
377 // mode_b conds are handled by gen_node_for_Proj
378 if(get_mode_sort(selector_mode) != irms_int_number)
381 assert(get_mode_size_bits(selector_mode) == 32);
384 defaultprojn = get_Cond_defaultProj(node);
386 // go over all projs to find min-&maxval of the switch
389 foreach_out_edge(node, edge) {
390 ir_node* proj = get_edge_src_irn(edge);
391 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
393 pn = get_Proj_proj(proj);
394 if(pn == defaultprojn) {
404 assert(defaultproj != NULL);
406 // subtract minval from the switch value
409 minval_const = new_rd_Const(dbg, irg, block, selector_mode, new_tarval_from_long(minval, selector_mode));
410 minval_const = gen_node_for_Const(env, dbg, irg, block, minval_const);
411 sub = new_rd_mips_sub(dbg, irg, block, selector, minval_const);
416 // compare if we're above maxval-minval or below zero.
417 // we can do this with 1 compare because we use unsigned mode
418 unsigned_mode = new_ir_mode(get_mode_name(selector_mode),
419 get_mode_sort(selector_mode), get_mode_size_bits(selector_mode),
420 0, get_mode_arithmetic(selector_mode), get_mode_modulo_shift(selector_mode));
422 max_const = new_rd_Const(dbg, irg, block, unsigned_mode, new_tarval_from_long(maxval - minval + 1, unsigned_mode));
423 max_const = gen_node_for_Const(env, dbg, irg, block, max_const);
424 sltu = new_rd_mips_slt(dbg, irg, block, sub, max_const);
426 zero = gen_zero_node(env, dbg, irg, block);
427 beq = new_rd_mips_beq(dbg, irg, block, sltu, zero, mode_T);
429 // attach defaultproj to beq now
430 set_irn_n(defaultproj, 0, beq);
431 set_Proj_proj(defaultproj, 1);
433 two_const = new_rd_Const(dbg, irg, block, unsigned_mode, new_tarval_from_long(2, unsigned_mode));
434 two_const = gen_node_for_Const(env, dbg, irg, block, two_const);
435 sl = new_rd_mips_sl(dbg, irg, block, sub, two_const);
437 la = new_rd_mips_la(dbg, irg, block);
438 add = new_rd_mips_addu(dbg, irg, block, sl, la);
439 load = new_rd_mips_load_r(dbg, irg, block, new_rd_NoMem(irg), add, mode_T);
440 attr = get_mips_attr(load);
441 attr->modes.load_store_mode = mode_Iu;
442 attr->tv = new_tarval_from_long(0, mode_Iu);
444 proj = new_rd_Proj(dbg, irg, block, load, mode_Iu, pn_Load_res);
446 switchjmp = new_rd_mips_SwitchJump(dbg, irg, block, proj, mode_T);
447 attr = get_mips_attr(switchjmp);
448 attr->switch_default_pn = defaultprojn;
450 edge = get_irn_out_edge_first(defaultproj);
451 defaultproj_succ = get_edge_src_irn(edge);
452 attr->symconst_id = new_id_from_str(mips_get_block_label(defaultproj_succ));
454 attr = get_mips_attr(la);
455 attr->symconst_id = new_id_from_str(mips_get_jumptbl_label(switchjmp));
462 ir_node *gen_node_for_Cond(mips_transform_env_t *env)
464 ir_graph *irg = env->irg;
465 ir_node *node = env->irn;
466 dbg_info *dbg = get_irn_dbg_info(node);
467 ir_node *block = get_nodes_block(node);
468 ir_node *sel_proj = get_Cond_selector(node);
469 ir_node *cmp = get_Proj_pred(sel_proj);
474 long pn = get_Proj_proj(sel_proj);
476 op1 = get_Cmp_left(cmp);
477 op2 = get_Cmp_right(cmp);
482 panic("mips backend can't handle unoptimized constant Cond");
485 res = new_rd_mips_beq(dbg, irg, block, op1, op2);
489 zero = gen_zero(env);
490 slt = new_rd_mips_slt(dbg, irg, block, op1, op2);
491 res = new_rd_mips_bne(dbg, irg, block, slt, zero);
495 zero = gen_zero(env);
496 slt = new_rd_mips_slt(dbg, irg, block, op2, op1);
497 res = new_rd_mips_beq(dbg, irg, block, slt, zero);
501 zero = gen_zero(env);
502 slt = new_rd_mips_slt(dbg, irg, block, op2, op1);
503 res = new_rd_mips_bne(dbg, irg, block, slt, zero);
507 zero = gen_zero(env);
508 slt = new_rd_mips_slt(dbg, irg, block, op2, op1);
509 res = new_rd_mips_bne(dbg, irg, block, slt, zero);
513 res = new_rd_mips_bne(dbg, irg, block, op1, op2);
517 panic("mips backend doesn't handle unordered compares yet");
523 static ir_node *create_conv_and(mips_transform_env_t *env, long immediate) {
524 ir_node *node = env->irn;
529 pred = get_Conv_op(node);
530 result = new_rd_mips_andi(env->dbg, env->irg, env->block, pred);
531 attr = get_mips_attr(result);
532 attr->tv = new_tarval_from_long(immediate, mode_Iu);
537 static ir_node *gen_node_for_Conv(mips_transform_env_t *env) {
538 ir_node *node = env->irn;
542 int dst_size, src_size;
544 pred = get_Conv_op(node);
545 srcmode = get_irn_mode(pred);
546 destmode = get_irn_mode(node);
548 dst_size = get_mode_size_bits(destmode);
549 src_size = get_mode_size_bits(srcmode);
551 if(src_size == dst_size) {
552 /* unnecessary conv */
557 if(srcmode->size >= destmode->size) {
558 assert(srcmode->size > destmode->size || srcmode->sign != destmode->sign);
559 return new_rd_mips_reinterpret_conv(env->dbg, env->irg, env->block, pred);
566 return create_conv_and(env, 0xff);
567 } else if(src_size == 16) {
568 return create_conv_and(env, 0xffff);
576 static ir_node *gen_node_mips_div(mips_transform_env_t *env, ir_node* op1, ir_node* op2, long p_div, long p_mod,
579 ir_node *node = env->irn;
581 const ir_edge_t *edge;
582 ir_mode *mode = get_irn_mode(node);
584 if(mode_is_signed(mode)) {
585 div = new_rd_mips_div(env->dbg, env->irg, env->block, op1, op2);
587 div = new_rd_mips_divu(env->dbg, env->irg, env->block, op1, op2);
591 foreach_out_edge(node, edge) {
592 ir_node *proj = get_edge_src_irn(edge);
593 long n = get_Proj_proj(proj);
594 assert(is_Proj(proj) && "non-Proj from Mod node");
596 set_Proj_proj(proj, pn_DivMod_res_div);
597 } else if (n == p_mod) {
598 set_Proj_proj(proj, pn_DivMod_res_mod);
599 } else if(n == p_m) {
600 set_Proj_proj(proj, pn_DivMod_M);
601 } else if(n == p_x) {
602 set_Proj_proj(proj, pn_DivMod_X_except);
604 assert(!"invalid proj");
611 static ir_node *gen_node_for_DivMod(mips_transform_env_t *env) {
612 ir_node *node = env->irn;
614 return gen_node_mips_div(env, get_DivMod_left(node), get_DivMod_right(node), pn_DivMod_res_div,
615 pn_DivMod_res_mod, pn_DivMod_M, pn_DivMod_X_except);
618 static ir_node *gen_node_for_Div(mips_transform_env_t *env) {
619 ir_node *node = env->irn;
621 return gen_node_mips_div(env, get_Div_left(node), get_Div_right(node), pn_Div_res, -1,
622 pn_Div_M, pn_Div_X_except);
625 static ir_node *gen_node_for_Mod(mips_transform_env_t *env) {
626 ir_node *node = env->irn;
628 return gen_node_mips_div(env, get_Mod_left(node), get_Mod_right(node), -1, pn_Mod_res,
629 pn_Mod_M, pn_Mod_X_except);
632 static ir_node *gen_node_for_Mul(mips_transform_env_t *env) {
633 ir_node *node = env->irn;
637 ir_mode *mode = get_irn_mode(node);
639 op1 = get_Mul_left(node);
640 op2 = get_Mul_right(node);
642 assert(get_mode_size_bits(env->mode) == 32);
643 assert(get_mode_size_bits(get_irn_mode(op1)) == get_mode_size_bits(env->mode));
644 assert(get_mode_size_bits(get_irn_mode(op2)) == get_mode_size_bits(env->mode));
646 if(mode_is_signed(mode)) {
647 mul = new_rd_mips_mult(env->dbg, env->irg, env->block, get_Mul_left(node), get_Mul_right(node));
649 mul = new_rd_mips_multu(env->dbg, env->irg, env->block, get_Mul_left(node), get_Mul_right(node));
651 mflo = new_rd_mips_mflo(env->dbg, env->irg, env->block, mul);
657 ir_node *gen_node_for_IJmp(mips_transform_env_t *env) {
658 ir_graph *irg = env->irg;
659 ir_node *node = env->irn;
660 dbg_info *dbg = get_irn_dbg_info(node);
661 ir_node *block = get_nodes_block(node);
662 ir_node *target = get_IJmp_target(node);
664 return new_rd_mips_jr(dbg, irg, block, target);
668 ir_node *gen_node_for_Jmp(mips_transform_env_t *env) {
669 ir_graph *irg = env->irg;
670 ir_node *node = env->irn;
671 dbg_info *dbg = get_irn_dbg_info(node);
672 ir_node *block = get_nodes_block(node);
674 return new_rd_mips_b(dbg, irg, block);
678 ir_node *gen_node_for_Abs(mips_transform_env_t *env) {
679 ir_node *node = env->irn;
680 ir_node *sra, *add, *xor;
683 // TODO for other bit sizes...
684 assert(get_mode_size_bits(env->mode) == 32);
685 sra = new_rd_mips_srai(env->dbg, env->irg, env->block, get_Abs_op(node));
686 attr = get_mips_attr(sra);
687 attr->tv = new_tarval_from_long(31, mode_Iu);
688 add = new_rd_mips_addu(env->dbg, env->irg, env->block, get_Abs_op(node), sra);
689 xor = new_rd_mips_xor(env->dbg, env->irg, env->block, sra, add);
695 ir_node *gen_node_for_Rot(mips_transform_env_t *env) {
696 ir_node *node = env->irn;
697 ir_node *subu, *srlv, *sllv, *or;
699 subu = new_rd_mips_subuzero(env->dbg, env->irg, env->block, get_Rot_right(node));
700 srlv = new_rd_mips_srlv(env->dbg, env->irg, env->block, get_Rot_left(node), subu);
701 sllv = new_rd_mips_sllv(env->dbg, env->irg, env->block, get_Rot_left(node), get_Rot_right(node));
702 or = new_rd_mips_or(env->dbg, env->irg, env->block, sllv, srlv);
707 static ir_node *gen_node_for_Unknown(mips_transform_env_t *env)
709 return gen_zero(env);
714 * lower a copyB into standard Firm assembler :-)
716 ir_node *gen_code_for_CopyB(ir_node *block, ir_node *node) {
718 ir_node *dst = get_CopyB_dst(node);
719 ir_node *src = get_CopyB_src(node);
720 ir_type *type = get_CopyB_type(node);
721 ir_node *mem = get_CopyB_mem(node);
723 ir_node *result = NULL;
724 int size = get_type_size_bytes(type);
725 dbg_info *dbg = get_irn_dbg_info(node);
726 ir_graph *irg = get_irn_irg(block);
731 ir_node *phi, *projT, *projF, *cmp, *proj, *cond, *jmp, *in[2];
732 ir_node *new_bl, *src_phi, *dst_phi, *mem_phi, *add;
733 ir_mode *p_mode = get_irn_mode(src);
736 /* build the control loop */
737 in[0] = in[1] = new_r_Unknown(irg, mode_X);
739 new_bl = new_r_Block(irg, 2, in);
741 in[0] = cnt = new_Const_long(mode_Is, (size >> 4));
742 in[1] = new_r_Unknown(irg, mode_Is);
743 phi = new_r_Phi(irg, new_bl, 2, in, mode_Is);
745 sub = new_rd_Sub(dbg, irg, new_bl, phi, new_Const_long(mode_Is, -1), mode_Is);
746 set_Phi_pred(phi, 1, sub);
748 cmp = new_rd_Cmp(dbg, irg, new_bl, sub, new_Const_long(mode_Is, 0));
749 proj = new_r_Proj(irg, new_bl, cmp, mode_b, pn_Cmp_Lg);
750 cond = new_rd_Cond(dbg, irg, new_bl, proj);
752 projT = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_true);
753 projF = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_false);
755 jmp = get_Block_cfgpred(block, 0);
756 set_Block_cfgpred(block, 0, projF);
758 set_Block_cfgpred(new_bl, 0, jmp);
759 set_Block_cfgpred(new_bl, 1, projT);
765 in[1] = new_r_Unknown(irg, p_mode);
766 src_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
769 dst_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
771 add = new_rd_Add(dbg, irg, new_bl, src_phi, new_Const_long(mode_Is, 16), p_mode);
772 set_Phi_pred(src_phi, 1, add);
773 add = new_rd_Add(dbg, irg, new_bl, dst_phi, new_Const_long(mode_Is, 16), p_mode);
774 set_Phi_pred(dst_phi, 1, add);
777 in[1] = new_r_Unknown(irg, mode_M);
778 mem_phi = new_r_Phi(irg, new_bl, 2, in, mode_M);
783 /* create 4 parallel loads */
784 for (i = 0; i < 4; ++i) {
787 load = new_rd_mips_load_r(dbg, irg, new_bl, mem_phi, src, mode_T);
788 attr = get_mips_attr(load);
789 attr->modes.load_store_mode = mode_Iu;
790 attr->tv = new_tarval_from_long(i * 4, mode_Iu);
792 ld[i] = new_rd_Proj(dbg, irg, new_bl, load, mode_Iu, pn_Load_res);
795 /* create 4 parallel stores */
796 for (i = 0; i < 4; ++i) {
799 store = new_rd_mips_store_r(dbg, irg, new_bl, mem_phi, dst, ld[i], mode_T);
800 attr = get_mips_attr(store);
801 attr->modes.load_store_mode = mode_Iu;
802 attr->tv = new_tarval_from_long(i * 4, mode_Iu);
804 mm[i] = new_rd_Proj(dbg, irg, new_bl, store, mode_M, pn_Store_M);
806 mem = new_r_Sync(irg, new_bl, 4, mm);
808 set_Phi_pred(mem_phi, 1, mem);
811 // output store/loads manually
813 for(i = size; i > 0; ) {
815 ir_node *load, *store, *projv;
816 int offset = size - i;
828 load = new_rd_mips_load_r(dbg, irg, block, mem, src, mode_T);
829 attr = get_mips_attr(load);
830 attr->modes.load_store_mode = mode;
831 attr->tv = new_tarval_from_long(offset, mode_Iu);
833 projv = new_rd_Proj(dbg, irg, block, load, mode, pn_Load_res);
835 store = new_rd_mips_store_r(dbg, irg, block, mem, dst, projv, mode_T);
836 attr = get_mips_attr(store);
837 attr->modes.load_store_mode = mode;
838 attr->tv = new_tarval_from_long(offset, mode_Iu);
840 mm[n] = new_rd_Proj(dbg, irg, block, store, mode_M, pn_Store_M);
845 result = new_r_Sync(irg, block, n, mm);
853 static void mips_fix_CopyB_Proj(mips_transform_env_t* env) {
854 ir_node *node = env->irn;
855 long n = get_Proj_proj(node);
857 if(n == pn_CopyB_M_except) {
859 } else if(n == pn_CopyB_M_regular) {
860 set_Proj_proj(node, pn_Store_M);
861 } else if(n == pn_CopyB_M_except) {
862 set_Proj_proj(node, pn_Store_X_except);
867 static void mips_transform_Spill(mips_transform_env_t* env) {
868 ir_node *node = env->irn;
869 ir_node *sched_point = NULL;
871 ir_node *nomem = new_rd_NoMem(env->irg);
872 ir_node *ptr = get_irn_n(node, 0);
873 ir_node *val = get_irn_n(node, 1);
874 ir_entity *ent = be_get_frame_entity(node);
877 if(sched_is_scheduled(node)) {
878 sched_point = sched_prev(node);
881 store = new_rd_mips_sw(env->dbg, env->irg, env->block, nomem, ptr, val);
882 attr = get_mips_attr(store);
883 attr->stack_entity = ent;
886 sched_add_after(sched_point, store);
890 exchange(node, store);
893 static void mips_transform_Reload(mips_transform_env_t* env) {
894 ir_node *node = env->irn;
895 ir_node *sched_point = NULL;
896 ir_node *load, *proj;
897 ir_node *ptr = get_irn_n(node, 0);
898 ir_node *mem = get_irn_n(node, 1);
899 ir_entity *ent = be_get_frame_entity(node);
900 const arch_register_t* reg;
903 if(sched_is_scheduled(node)) {
904 sched_point = sched_prev(node);
907 load = new_rd_mips_lw(env->dbg, env->irg, env->block, mem, ptr);
908 attr = get_mips_attr(load);
909 attr->stack_entity = ent;
911 proj = new_rd_Proj(env->dbg, env->irg, env->block, load, mode_Iu, pn_mips_lw_res);
914 sched_add_after(sched_point, load);
915 sched_add_after(load, proj);
920 /* copy the register from the old node to the new Load */
921 reg = arch_get_irn_register(env->cg->arch_env, node);
922 arch_set_irn_register(env->cg->arch_env, proj, reg);
924 exchange(node, proj);
928 static ir_node *gen_node_for_StackParam(mips_transform_env_t *env)
930 ir_node *node = env->irn;
931 ir_node *sp = get_irn_n(node, 0);
933 ir_node *nomem = new_rd_NoMem(env->irg);
937 load = new_rd_mips_load_r(env->dbg, env->irg, env->block, nomem, sp, mode_T);
938 attr = get_mips_attr(load);
939 attr->stack_entity = be_get_frame_entity(node);
940 attr->modes.load_store_mode = env->mode;
942 proj = new_rd_Proj(env->dbg, env->irg, env->block, load, env->mode, pn_Load_res);
948 static ir_node *gen_node_for_AddSP(mips_transform_env_t *env)
950 ir_node *node = env->irn;
953 const arch_register_t *reg;
955 op1 = get_irn_n(node, 0);
956 op2 = get_irn_n(node, 1);
958 add = new_rd_mips_addu(env->dbg, env->irg, env->block, op1, op2);
960 /* copy the register requirements from the old node to the new node */
961 reg = arch_get_irn_register(env->cg->arch_env, node);
962 arch_set_irn_register(env->cg->arch_env, add, reg);
967 /*********************************************************
970 * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
971 * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
972 * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
973 * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
975 *********************************************************/
979 * Transforms the given firm node (and maybe some other related nodes)
980 * into one or more assembler nodes.
982 * @param node the firm node
983 * @param env the debug module
985 void mips_transform_node(ir_node *node, void *env) {
986 mips_code_gen_t *cgenv = (mips_code_gen_t *)env;
987 ir_opcode code = get_irn_opcode(node);
988 ir_node *asm_node = node;
989 mips_transform_env_t tenv;
994 tenv.block = get_nodes_block(node);
995 tenv.dbg = get_irn_dbg_info(node);
996 tenv.irg = current_ir_graph;
998 tenv.mode = get_irn_mode(node);
1001 #define UNOP(firm_opcode, mips_nodetype) case iro_##firm_opcode: asm_node = mips_gen_##mips_nodetype(&tenv, get_##firm_opcode##_op(node)); break
1002 #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
1003 #define IGN(a) case iro_##a: break
1004 #define BAD(a) case iro_##a: goto bad
1018 asm_node = gen_node_for_Abs(&tenv);
1022 asm_node = gen_node_for_Rot(&tenv);
1026 asm_node = gen_node_for_Div(&tenv);
1030 asm_node = gen_node_for_Mod(&tenv);
1034 asm_node = gen_node_for_Load(&tenv);
1038 asm_node = gen_node_for_Store(&tenv);
1042 asm_node = gen_node_for_Proj(&tenv);
1046 asm_node = gen_node_for_Conv(&tenv);
1050 asm_node = gen_node_for_DivMod(&tenv);
1054 asm_node = gen_node_for_Mul(&tenv);
1058 asm_node = gen_node_for_Jmp(&tenv);
1062 asm_node = gen_node_for_IJmp(&tenv);
1066 asm_node = gen_node_for_Unknown(&tenv);
1070 asm_node = gen_node_for_Cond(&tenv);
1074 asm_node = gen_node_for_Phi(&tenv);
1077 /* TODO: implement these nodes */
1080 /* You probably don't need to handle the following nodes */
1082 // call is handled in the emit phase
1084 // Cmp is handled together with Cond
1113 if(be_is_StackParam(node)) {
1114 //asm_node = gen_node_for_StackParam(&tenv);
1115 } else if(be_is_AddSP(node)) {
1116 asm_node = gen_node_for_AddSP(&tenv);
1121 fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
1125 if (asm_node != node) {
1126 exchange(node, asm_node);
1130 void mips_pre_transform_node(ir_node *node, void *env) {
1131 mips_code_gen_t *cgenv = (mips_code_gen_t *)env;
1134 mips_transform_env_t tenv;
1139 tenv.block = get_nodes_block(node);
1140 tenv.dbg = get_irn_dbg_info(node);
1141 tenv.irg = current_ir_graph;
1143 tenv.mode = get_irn_mode(node);
1148 ir_node* pred = get_Proj_pred(node);
1149 if(get_irn_opcode(pred) == iro_CopyB) {
1150 mips_fix_CopyB_Proj(&tenv);
1155 for(i = 0; i < get_irn_arity(node); ++i) {
1156 ir_node* pred = get_irn_n(node, i);
1158 if (is_Const(pred)) {
1159 ir_node* constnode = exchange_node_for_Const(&tenv, pred, i);
1160 set_irn_n(node, i, constnode);
1161 } else if (get_irn_op(pred) == op_SymConst) {
1162 ir_node* constnode = gen_node_for_SymConst(&tenv, pred, i);
1163 set_irn_n(node, i, constnode);
1169 * Calls the transform functions for Spill and Reload.
1171 void mips_after_ra_walker(ir_node *node, void *env) {
1172 mips_code_gen_t *cg = env;
1173 mips_transform_env_t tenv;
1178 tenv.block = get_nodes_block(node);
1179 tenv.dbg = get_irn_dbg_info(node);
1180 tenv.irg = current_ir_graph;
1182 tenv.mode = get_irn_mode(node);
1185 if (be_is_Reload(node)) {
1186 mips_transform_Reload(&tenv);
1187 } else if (be_is_Spill(node)) {
1188 mips_transform_Spill(&tenv);