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"
43 #include "../benode_t.h"
45 #include "../besched.h"
46 #include "../besched_t.h"
47 #include "../beirg_t.h"
48 #include "bearch_mips_t.h"
50 #include "mips_nodes_attr.h"
51 #include "../arch/archop.h" /* we need this for Min and Max nodes */
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 #define MIPS_GENBINFUNC(mips_nodetype) \
71 static ir_node* mips_gen_##mips_nodetype(mips_transform_env_t *env, ir_node *op1, ir_node *op2) {\
72 ASSERT_NO_FLOAT(env->mode); \
73 /*assert(get_irn_mode(op1) == get_irn_mode(op2));*/ \
74 /*assert(get_irn_mode(op1) == env->mode);*/ \
75 assert(get_mode_size_bits(env->mode) == 32); \
76 return new_rd_mips_##mips_nodetype(env->dbg, env->irg, env->block, op1, op2); \
88 #define MIPS_GENUNFUNC(mips_nodetype) \
89 static ir_node *mips_gen_##mips_nodetype(mips_transform_env_t *env, ir_node *op) { \
90 ASSERT_NO_FLOAT(env->mode); \
91 assert(get_irn_mode(op) == env->mode); \
92 assert(get_mode_size_bits(env->mode) == 32); \
93 return new_rd_mips_##mips_nodetype(env->dbg, env->irg, env->block, op); \
98 static ir_node* mips_get_reg_node(mips_transform_env_t *env, const arch_register_t *reg) {
99 return be_abi_get_callee_save_irn(env->cg->birg->abi, reg);
102 static ir_node* gen_zero_node(mips_transform_env_t *env, dbg_info *ebg, ir_graph *irg, ir_node *block)
104 ir_node *zero = be_abi_get_callee_save_irn(env->cg->birg->abi, &mips_gp_regs[REG_ZERO]);
105 // TODO make zero nodes work
106 //ir_node *unknown = new_rd_mips_zero(dbg, irg, block, mode);
111 static ir_node* gen_node_for_Const(mips_transform_env_t *env, dbg_info *dbg, ir_graph *irg, ir_node *block, ir_node *constant)
113 tarval* tv = get_Const_tarval(constant);
117 ir_mode* mode = get_irn_mode(constant);
118 unsigned long val, lower, upper;
120 val = get_tarval_long(tv);
122 return gen_zero_node(env, dbg, irg, block);
124 lower = val & 0xffff;
125 upper = (val >> 16) & 0xffff;
127 ir_node *zero = gen_zero_node(env, dbg, irg, block);
128 ir_node *lli = new_rd_mips_lli(dbg, irg, block, zero);
129 attr = get_mips_attr(lli);
130 attr->tv = new_tarval_from_long(val, mode);
135 lui = new_rd_mips_lui(dbg, irg, block);
136 attr = get_mips_attr(lui);
137 attr->tv = new_tarval_from_long(val, mode);
142 lli = new_rd_mips_lli(dbg, irg, block, lui);
143 attr = get_mips_attr(lli);
144 attr->tv = new_tarval_from_long(val, mode);
149 static ir_node* exchange_node_for_Const(mips_transform_env_t *env, ir_node* pred, int n) {
150 ir_node *node = env->irn;
151 dbg_info *dbg = get_irn_dbg_info(pred);
152 ir_graph *irg = get_irn_irg(node);
155 if(get_irn_opcode(node) == iro_Phi) {
156 ir_node *phipred = get_nodes_block(node);
157 block = get_Block_cfgpred_block(phipred, n);
159 block = get_nodes_block(node);
162 return gen_node_for_Const(env, dbg, irg, block, pred);
165 static ir_node* gen_node_for_SymConst(mips_transform_env_t *env, ir_node* pred, int n) {
169 ir_node *node = env->irn;
170 dbg_info *dbg = get_irn_dbg_info(pred);
171 ir_graph *irg = get_irn_irg(node);
175 ir_node *phipred = get_nodes_block(node);
176 block = get_Block_cfgpred_block(phipred, n);
178 block = get_nodes_block(node);
181 kind = get_SymConst_kind(pred);
182 if(kind == symconst_addr_ent) {
183 result = new_rd_mips_la(dbg, irg, block);
184 attr = get_mips_attr(result);
185 attr->symconst_id = get_entity_ld_ident(get_SymConst_entity(pred));
187 } else if(kind == symconst_addr_name) {
188 result = new_rd_mips_la(dbg, irg, block);
189 attr = get_mips_attr(result);
190 attr->symconst_id = get_SymConst_name(pred);
200 * Generates a mips node for a firm Load node
202 static ir_node *gen_node_for_Load(mips_transform_env_t *env) {
203 ir_node *node = env->irn;
204 ir_node *result = NULL;
209 ASSERT_NO_FLOAT(get_irn_mode(node));
211 mode = get_Load_mode(node);
212 assert(mode->vector_elem == 1);
213 assert(mode->sort == irms_int_number || mode->sort == irms_reference);
215 load_ptr = get_Load_ptr(node);
216 assert(get_mode_sort(mode) == irms_reference || get_mode_sort(mode) == irms_int_number);
217 result = new_rd_mips_load_r(env->dbg, env->irg, env->block,
218 get_Load_mem(node), load_ptr, get_irn_mode(node));
220 attr = get_mips_attr(result);
221 attr->tv = new_tarval_from_long(0, mode_Iu);
222 attr->modes.load_store_mode = mode;
228 * Generates a mips node for a firm Store node
230 static ir_node *gen_node_for_Store(mips_transform_env_t *env) {
231 ir_node *node = env->irn;
232 ir_node *result = NULL;
237 ASSERT_NO_FLOAT(env->mode);
239 store_ptr = get_Store_ptr(node);
240 mode = get_irn_mode(store_ptr);
241 assert(mode->vector_elem == 1);
242 assert(mode->sort == irms_int_number || mode->sort == irms_reference);
244 if(get_irn_opcode(store_ptr) == iro_SymConst) {
245 result = new_rd_mips_store_i(env->dbg, env->irg, env->block, get_Store_mem(node),
246 get_Store_ptr(node), get_Store_value(node), env->mode);
248 result = new_rd_mips_store_r(env->dbg, env->irg, env->block, get_Store_mem(node),
249 get_Store_ptr(node), get_Store_value(node), env->mode);
251 attr = get_mips_attr(result);
252 attr->tv = new_tarval_from_long(0, mode_Iu);
253 attr->modes.load_store_mode = mode;
258 static ir_node *gen_node_for_div_Proj(mips_transform_env_t *env) {
259 ir_node *proj = env->irn;
261 ir_node *pred = get_irn_n(proj, 0);
265 n = get_Proj_proj(proj);
267 // set the div mode to the DivMod node
268 attr = get_mips_attr(pred);
269 assert(attr->modes.original_mode == NULL || attr->modes.original_mode == env->mode);
270 attr->modes.original_mode = env->mode;
272 // we have to construct a new proj here, to avoid circular refs that
273 // happen when we reuse the old one
274 new_proj = new_ir_node(env->dbg, env->irg, env->block, op_Proj, mode_ANY, 1, &pred);
275 set_Proj_proj(new_proj, n);
277 if(n == pn_DivMod_res_div) {
278 return new_rd_mips_mflo(env->dbg, env->irg, env->block, new_proj);
279 } else if(n == pn_DivMod_res_mod) {
280 return new_rd_mips_mfhi(env->dbg, env->irg, env->block, new_proj);
286 static ir_node *make_jmp_or_fallthrough(mips_transform_env_t *env)
288 const ir_edge_t *edge;
289 ir_node *node = env->irn;
291 int our_block_sched_nr = mips_get_block_sched_nr(get_nodes_block(node));
293 edge = get_irn_out_edge_first(node);
294 next_block = get_edge_src_irn(edge);
296 if(mips_get_sched_block(env->cg, our_block_sched_nr + 1) == next_block) {
297 return new_rd_mips_fallthrough(env->dbg, env->irg, env->block, mode_X);
300 return new_rd_mips_b(env->dbg, env->irg, env->block, mode_X);
303 static ir_node *gen_node_for_Cond_Proj(mips_transform_env_t *env, ir_node* node, int true_false)
305 // we can't use get_Cond_selector here because the selector is already
306 // replaced by a mips_ compare node
307 ir_node *proj = get_Cond_selector(node);
308 ir_node *original_cmp = get_irn_n(proj, 0);
312 dbg_info *dbg = env->dbg;
313 ir_graph *irg = env->irg;
314 ir_node *block = env->block;
317 n = get_Proj_proj(proj);
318 assert(n < 8 && "Only ordered comps supported");
320 assert(get_irn_opcode(original_cmp) == iro_Cmp);
321 op1 = get_Cmp_left(original_cmp);
322 op2 = get_Cmp_right(original_cmp);
329 return make_jmp_or_fallthrough(env);
333 return make_jmp_or_fallthrough(env);
335 condjmp = new_rd_mips_beq(dbg, irg, block, op1, op2, mode_T);
336 return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
340 return make_jmp_or_fallthrough(env);
342 cmp = new_rd_mips_slt(dbg, irg, block, op1, op2);
343 condjmp = new_rd_mips_bgtz(dbg, irg, block, cmp, mode_T);
344 return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
348 return make_jmp_or_fallthrough(env);
350 cmp = new_rd_mips_slt(dbg, irg, block, op2, op1);
351 condjmp = new_rd_mips_blez(dbg, irg, block, cmp, mode_T);
352 return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
356 return make_jmp_or_fallthrough(env);
358 cmp = new_rd_mips_slt(dbg, irg, block, op2, op1);
359 condjmp = new_rd_mips_bgtz(dbg, irg, block, cmp, mode_T);
360 return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
364 return make_jmp_or_fallthrough(env);
366 cmp = new_rd_mips_slt(dbg, irg, block, op1, op2);
367 condjmp = new_rd_mips_blez(dbg, irg, block, cmp, mode_T);
368 return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
372 return make_jmp_or_fallthrough(env);
374 condjmp = new_rd_mips_bne(dbg, irg, block, op1, op2, mode_T);
375 return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
381 return make_jmp_or_fallthrough(env);
390 static ir_node *gen_node_for_Proj(mips_transform_env_t *env)
392 ir_node *proj = env->irn;
394 ir_node *predecessor = get_Proj_pred(proj);
396 // all DivMods, Div, Mod should be replaced by now
397 assert(get_irn_opcode(predecessor) != iro_DivMod);
398 assert(get_irn_opcode(predecessor) != iro_Div);
399 assert(get_irn_opcode(predecessor) != iro_Mod);
401 if(is_mips_div(predecessor))
402 return gen_node_for_div_Proj(env);
404 if(get_irn_opcode(predecessor) == iro_Cond) {
405 ir_node *selector = get_Cond_selector(predecessor);
406 ir_mode *mode = get_irn_mode(selector);
407 n = get_Proj_proj(proj);
409 if(get_mode_sort(mode) == irms_internal_boolean) {
410 assert(n == pn_Cond_true || n == pn_Cond_false);
411 return gen_node_for_Cond_Proj(env, predecessor, n == pn_Cond_true);
418 static ir_node *gen_node_for_Cond(mips_transform_env_t *env)
420 ir_node *selector = get_Cond_selector(env->irn);
421 ir_mode *selector_mode = get_irn_mode(selector);
422 ir_node *node = env->irn;
423 dbg_info *dbg = env->dbg;
424 ir_graph *irg = env->irg;
425 ir_node *block = env->block;
426 ir_node *sub, *sltu, *minval_const, *max_const, *switchjmp;
427 ir_node *defaultproj, *defaultproj_succ;
429 long pn, minval, maxval, defaultprojn;
430 const ir_edge_t *edge;
431 ir_node *zero, *two_const, *add, *la, *load, *proj;
432 ir_mode *unsigned_mode;
435 // mode_b conds are handled by gen_node_for_Proj
436 if(get_mode_sort(selector_mode) != irms_int_number)
439 assert(get_mode_size_bits(selector_mode) == 32);
442 defaultprojn = get_Cond_defaultProj(node);
444 // go over all projs to find min-&maxval of the switch
447 foreach_out_edge(node, edge) {
448 ir_node* proj = get_edge_src_irn(edge);
449 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
451 pn = get_Proj_proj(proj);
452 if(pn == defaultprojn) {
462 assert(defaultproj != NULL);
464 // subtract minval from the switch value
467 minval_const = new_rd_Const(dbg, irg, block, selector_mode, new_tarval_from_long(minval, selector_mode));
468 minval_const = gen_node_for_Const(env, dbg, irg, block, minval_const);
469 sub = new_rd_mips_sub(dbg, irg, block, selector, minval_const);
474 // compare if we're above maxval-minval or below zero.
475 // we can do this with 1 compare because we use unsigned mode
476 unsigned_mode = new_ir_mode(get_mode_name(selector_mode),
477 get_mode_sort(selector_mode), get_mode_size_bits(selector_mode),
478 0, get_mode_arithmetic(selector_mode), get_mode_modulo_shift(selector_mode));
480 max_const = new_rd_Const(dbg, irg, block, unsigned_mode, new_tarval_from_long(maxval - minval + 1, unsigned_mode));
481 max_const = gen_node_for_Const(env, dbg, irg, block, max_const);
482 sltu = new_rd_mips_slt(dbg, irg, block, sub, max_const);
484 zero = gen_zero_node(env, dbg, irg, block);
485 beq = new_rd_mips_beq(dbg, irg, block, sltu, zero, mode_T);
487 // attach defaultproj to beq now
488 set_irn_n(defaultproj, 0, beq);
489 set_Proj_proj(defaultproj, 1);
491 two_const = new_rd_Const(dbg, irg, block, unsigned_mode, new_tarval_from_long(2, unsigned_mode));
492 two_const = gen_node_for_Const(env, dbg, irg, block, two_const);
493 sl = new_rd_mips_sl(dbg, irg, block, sub, two_const);
495 la = new_rd_mips_la(dbg, irg, block);
496 add = new_rd_mips_addu(dbg, irg, block, sl, la);
497 load = new_rd_mips_load_r(dbg, irg, block, new_rd_NoMem(irg), add, mode_T);
498 attr = get_mips_attr(load);
499 attr->modes.load_store_mode = mode_Iu;
500 attr->tv = new_tarval_from_long(0, mode_Iu);
502 proj = new_rd_Proj(dbg, irg, block, load, mode_Iu, pn_Load_res);
504 switchjmp = new_rd_mips_SwitchJump(dbg, irg, block, proj, mode_T);
505 attr = get_mips_attr(switchjmp);
506 attr->switch_default_pn = defaultprojn;
508 edge = get_irn_out_edge_first(defaultproj);
509 defaultproj_succ = get_edge_src_irn(edge);
510 attr->symconst_id = new_id_from_str(mips_get_block_label(defaultproj_succ));
512 attr = get_mips_attr(la);
513 attr->symconst_id = new_id_from_str(mips_get_jumptbl_label(switchjmp));
518 static ir_node *create_conv_store_load(mips_transform_env_t *env, ir_mode* srcmode, ir_mode* dstmode) {
519 ir_node *nomem, *store, *mem_proj, *value_proj, *load;
520 ir_entity *mem_entity;
521 ir_node *node = env->irn;
522 ir_node *pred = get_Conv_op(node);
524 // TODO HACK make this global...
527 ir_type *ptr_i32type;
530 id = new_id_from_str("__conv0");
531 i32type = new_type_primitive(new_id_from_str("ptr32"), mode_Iu);
532 ptr_i32type = new_d_type_pointer(id, i32type, mode_P, env->dbg);
533 mem_entity = new_d_entity(get_irg_frame_type(env->irg), id, ptr_i32type, env->dbg);
535 sp = mips_get_reg_node(env, &mips_gp_regs[REG_SP]);
536 nomem = new_ir_node(env->dbg, env->irg, env->block, op_NoMem, mode_M, 0, NULL);
538 store = new_rd_mips_store_r(env->dbg, env->irg, env->block, nomem, sp, pred, mode_T);
539 attr = get_mips_attr(store);
540 attr->tv = new_tarval_from_long(0, mode_Iu);
541 attr->modes.load_store_mode = srcmode;
542 attr->stack_entity = mem_entity;
544 mem_proj = new_ir_node(env->dbg, env->irg, env->block, op_Proj, mode_M, 1, &store);
545 set_Proj_proj(mem_proj, pn_Store_M);
547 load = new_rd_mips_load_r(env->dbg, env->irg, env->block, mem_proj, sp, mode_T);
548 attr = get_mips_attr(load);
549 attr->tv = new_tarval_from_long(0, mode_Iu);
550 attr->modes.load_store_mode = dstmode;
551 attr->stack_entity = mem_entity;
553 value_proj = new_ir_node(env->dbg, env->irg, env->block, op_Proj, env->mode, 1, &load);
554 set_Proj_proj(value_proj, pn_Load_res);
559 static ir_node *create_conv_and(mips_transform_env_t *env, long immediate) {
560 ir_node *node = env->irn;
565 pred = get_Conv_op(node);
566 result = new_rd_mips_andi(env->dbg, env->irg, env->block, pred);
567 attr = get_mips_attr(result);
568 attr->tv = new_tarval_from_long(immediate, mode_Iu);
573 static ir_node *gen_node_for_Conv(mips_transform_env_t *env) {
574 ir_node *node = env->irn;
578 int dst_size, src_size;
580 pred = get_Conv_op(node);
581 srcmode = get_irn_mode(pred);
582 destmode = get_irn_mode(node);
584 dst_size = get_mode_size_bits(destmode);
585 src_size = get_mode_size_bits(srcmode);
587 if(srcmode->size >= destmode->size) {
588 assert(srcmode->size > destmode->size || srcmode->sign != destmode->sign);
589 return new_rd_mips_reinterpret_conv(env->dbg, env->irg, env->block, pred);
592 if(srcmode->size == 8) {
593 return create_conv_store_load(env, mode_Bs, mode_Bs);
594 } else if(srcmode->size == 16) {
595 return create_conv_store_load(env, mode_Hs, mode_Hs);
599 return create_conv_and(env, 0xff);
600 } else if(src_size == 16) {
601 return create_conv_and(env, 0xffff);
609 static ir_node *gen_node_mips_div(mips_transform_env_t *env, ir_node* op1, ir_node* op2, long p_div, long p_mod,
612 ir_node *node = env->irn;
614 const ir_edge_t *edge;
615 ir_mode *mode = get_irn_mode(node);
617 if(mode_is_signed(mode)) {
618 div = new_rd_mips_div(env->dbg, env->irg, env->block, op1, op2);
620 div = new_rd_mips_divu(env->dbg, env->irg, env->block, op1, op2);
624 foreach_out_edge(node, edge) {
625 ir_node *proj = get_edge_src_irn(edge);
626 long n = get_Proj_proj(proj);
627 assert(is_Proj(proj) && "non-Proj from Mod node");
629 set_Proj_proj(proj, pn_DivMod_res_div);
630 } else if (n == p_mod) {
631 set_Proj_proj(proj, pn_DivMod_res_mod);
632 } else if(n == p_m) {
633 set_Proj_proj(proj, pn_DivMod_M);
634 } else if(n == p_x) {
635 set_Proj_proj(proj, pn_DivMod_X_except);
637 assert(!"invalid proj");
644 static ir_node *gen_node_for_DivMod(mips_transform_env_t *env) {
645 ir_node *node = env->irn;
647 return gen_node_mips_div(env, get_DivMod_left(node), get_DivMod_right(node), pn_DivMod_res_div,
648 pn_DivMod_res_mod, pn_DivMod_M, pn_DivMod_X_except);
651 static ir_node *gen_node_for_Div(mips_transform_env_t *env) {
652 ir_node *node = env->irn;
654 return gen_node_mips_div(env, get_Div_left(node), get_Div_right(node), pn_Div_res, -1,
655 pn_Div_M, pn_Div_X_except);
658 static ir_node *gen_node_for_Mod(mips_transform_env_t *env) {
659 ir_node *node = env->irn;
661 return gen_node_mips_div(env, get_Mod_left(node), get_Mod_right(node), -1, pn_Mod_res,
662 pn_Mod_M, pn_Mod_X_except);
665 static ir_node *gen_node_for_Mul(mips_transform_env_t *env) {
666 ir_node *node = env->irn;
670 ir_mode *mode = get_irn_mode(node);
672 op1 = get_Mul_left(node);
673 op2 = get_Mul_right(node);
675 assert(get_mode_size_bits(env->mode) == 32);
676 assert(get_mode_size_bits(get_irn_mode(op1)) == get_mode_size_bits(env->mode));
677 assert(get_mode_size_bits(get_irn_mode(op2)) == get_mode_size_bits(env->mode));
679 if(mode_is_signed(mode)) {
680 mul = new_rd_mips_mult(env->dbg, env->irg, env->block, get_Mul_left(node), get_Mul_right(node));
682 mul = new_rd_mips_multu(env->dbg, env->irg, env->block, get_Mul_left(node), get_Mul_right(node));
684 mflo = new_rd_mips_mflo(env->dbg, env->irg, env->block, mul);
689 static ir_node *gen_node_for_IJmp(mips_transform_env_t *env) {
690 ir_node *node = env->irn;
692 return new_rd_mips_j(env->dbg, env->irg, env->block, get_IJmp_target(node), node->mode);
695 static ir_node *gen_node_for_Jmp(mips_transform_env_t *env) {
696 return make_jmp_or_fallthrough(env);
699 static ir_node *gen_node_for_Abs(mips_transform_env_t *env) {
700 ir_node *node = env->irn;
701 ir_node *sra, *add, *xor;
704 // TODO for other bit sizes...
705 assert(get_mode_size_bits(env->mode) == 32);
706 sra = new_rd_mips_srai(env->dbg, env->irg, env->block, get_Abs_op(node));
707 attr = get_mips_attr(sra);
708 attr->tv = new_tarval_from_long(31, mode_Iu);
709 add = new_rd_mips_addu(env->dbg, env->irg, env->block, get_Abs_op(node), sra);
710 xor = new_rd_mips_xor(env->dbg, env->irg, env->block, sra, add);
715 static ir_node *gen_node_for_Rot(mips_transform_env_t *env) {
716 ir_node *node = env->irn;
717 ir_node *subu, *srlv, *sllv, *or;
719 subu = new_rd_mips_subuzero(env->dbg, env->irg, env->block, get_Rot_right(node));
720 srlv = new_rd_mips_srlv(env->dbg, env->irg, env->block, get_Rot_left(node), subu);
721 sllv = new_rd_mips_sllv(env->dbg, env->irg, env->block, get_Rot_left(node), get_Rot_right(node));
722 or = new_rd_mips_or(env->dbg, env->irg, env->block, sllv, srlv);
727 static ir_node *gen_node_for_Unknown(mips_transform_env_t *env)
729 return gen_zero_node(env, env->dbg, env->irg, env->block);
733 * lower a copyB into standard Firm assembler :-)
735 ir_node *gen_code_for_CopyB(ir_node *block, ir_node *node) {
737 ir_node *dst = get_CopyB_dst(node);
738 ir_node *src = get_CopyB_src(node);
739 ir_type *type = get_CopyB_type(node);
740 ir_node *mem = get_CopyB_mem(node);
742 ir_node *result = NULL;
743 int size = get_type_size_bytes(type);
744 dbg_info *dbg = get_irn_dbg_info(node);
745 ir_graph *irg = get_irn_irg(block);
750 ir_node *phi, *projT, *projF, *cmp, *proj, *cond, *jmp, *in[2];
751 ir_node *new_bl, *src_phi, *dst_phi, *mem_phi, *add;
752 ir_mode *p_mode = get_irn_mode(src);
755 /* build the control loop */
756 in[0] = in[1] = new_r_Unknown(irg, mode_X);
758 new_bl = new_r_Block(irg, 2, in);
760 in[0] = cnt = new_Const_long(mode_Is, (size >> 4));
761 in[1] = new_r_Unknown(irg, mode_Is);
762 phi = new_r_Phi(irg, new_bl, 2, in, mode_Is);
764 sub = new_rd_Sub(dbg, irg, new_bl, phi, new_Const_long(mode_Is, -1), mode_Is);
765 set_Phi_pred(phi, 1, sub);
767 cmp = new_rd_Cmp(dbg, irg, new_bl, sub, new_Const_long(mode_Is, 0));
768 proj = new_r_Proj(irg, new_bl, cmp, mode_b, pn_Cmp_Lg);
769 cond = new_rd_Cond(dbg, irg, new_bl, proj);
771 projT = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_true);
772 projF = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_false);
774 jmp = get_Block_cfgpred(block, 0);
775 set_Block_cfgpred(block, 0, projF);
777 set_Block_cfgpred(new_bl, 0, jmp);
778 set_Block_cfgpred(new_bl, 1, projT);
784 in[1] = new_r_Unknown(irg, p_mode);
785 src_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
788 dst_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
790 add = new_rd_Add(dbg, irg, new_bl, src_phi, new_Const_long(mode_Is, 16), p_mode);
791 set_Phi_pred(src_phi, 1, add);
792 add = new_rd_Add(dbg, irg, new_bl, dst_phi, new_Const_long(mode_Is, 16), p_mode);
793 set_Phi_pred(dst_phi, 1, add);
796 in[1] = new_r_Unknown(irg, mode_M);
797 mem_phi = new_r_Phi(irg, new_bl, 2, in, mode_M);
802 /* create 4 parallel loads */
803 for (i = 0; i < 4; ++i) {
806 load = new_rd_mips_load_r(dbg, irg, new_bl, mem_phi, src, mode_T);
807 attr = get_mips_attr(load);
808 attr->modes.load_store_mode = mode_Iu;
809 attr->tv = new_tarval_from_long(i * 4, mode_Iu);
811 ld[i] = new_rd_Proj(dbg, irg, new_bl, load, mode_Iu, pn_Load_res);
814 /* create 4 parallel stores */
815 for (i = 0; i < 4; ++i) {
818 store = new_rd_mips_store_r(dbg, irg, new_bl, mem_phi, dst, ld[i], mode_T);
819 attr = get_mips_attr(store);
820 attr->modes.load_store_mode = mode_Iu;
821 attr->tv = new_tarval_from_long(i * 4, mode_Iu);
823 mm[i] = new_rd_Proj(dbg, irg, new_bl, store, mode_M, pn_Store_M);
825 mem = new_r_Sync(irg, new_bl, 4, mm);
827 set_Phi_pred(mem_phi, 1, mem);
830 // output store/loads manually
832 for(i = size; i > 0; ) {
834 ir_node *load, *store, *projv;
835 int offset = size - i;
847 load = new_rd_mips_load_r(dbg, irg, block, mem, src, mode_T);
848 attr = get_mips_attr(load);
849 attr->modes.load_store_mode = mode;
850 attr->tv = new_tarval_from_long(offset, mode_Iu);
852 projv = new_rd_Proj(dbg, irg, block, load, mode, pn_Load_res);
854 store = new_rd_mips_store_r(dbg, irg, block, mem, dst, projv, mode_T);
855 attr = get_mips_attr(store);
856 attr->modes.load_store_mode = mode;
857 attr->tv = new_tarval_from_long(offset, mode_Iu);
859 mm[n] = new_rd_Proj(dbg, irg, block, store, mode_M, pn_Store_M);
864 result = new_r_Sync(irg, block, n, mm);
872 static void mips_fix_CopyB_Proj(mips_transform_env_t* env) {
873 ir_node *node = env->irn;
874 long n = get_Proj_proj(node);
876 if(n == pn_CopyB_M_except) {
878 } else if(n == pn_CopyB_M_regular) {
879 set_Proj_proj(node, pn_Store_M);
880 } else if(n == pn_CopyB_M_except) {
881 set_Proj_proj(node, pn_Store_X_except);
885 static void mips_transform_Spill(mips_transform_env_t* env) {
886 ir_node *node = env->irn;
887 ir_node *sched_point = NULL;
888 ir_node *store, *proj;
889 ir_node *nomem = new_rd_NoMem(env->irg);
890 ir_node *ptr = get_irn_n(node, 0);
891 ir_node *val = get_irn_n(node, 1);
892 ir_entity *ent = be_get_frame_entity(node);
895 if(sched_is_scheduled(node)) {
896 sched_point = sched_prev(node);
899 store = new_rd_mips_store_r(env->dbg, env->irg, env->block, nomem, ptr, val, mode_T);
900 attr = get_mips_attr(store);
901 attr->stack_entity = ent;
902 attr->modes.load_store_mode = get_irn_mode(val);
904 proj = new_rd_Proj(env->dbg, env->irg, env->block, store, mode_M, pn_Store_M);
907 sched_add_after(sched_point, store);
908 sched_add_after(store, proj);
913 exchange(node, proj);
916 static void mips_transform_Reload(mips_transform_env_t* env) {
917 ir_node *node = env->irn;
918 ir_node *sched_point = NULL;
919 ir_node *load, *proj;
920 ir_node *ptr = get_irn_n(node, 0);
921 ir_node *mem = get_irn_n(node, 1);
922 ir_mode *mode = get_irn_mode(node);
923 ir_entity *ent = be_get_frame_entity(node);
924 const arch_register_t* reg;
927 if(sched_is_scheduled(node)) {
928 sched_point = sched_prev(node);
931 load = new_rd_mips_load_r(env->dbg, env->irg, env->block, mem, ptr, mode_T);
932 attr = get_mips_attr(load);
933 attr->stack_entity = ent;
934 attr->modes.load_store_mode = mode;
936 proj = new_rd_Proj(env->dbg, env->irg, env->block, load, mode, pn_Load_res);
939 sched_add_after(sched_point, load);
940 sched_add_after(load, proj);
945 /* copy the register from the old node to the new Load */
946 reg = arch_get_irn_register(env->cg->arch_env, node);
947 arch_set_irn_register(env->cg->arch_env, proj, reg);
949 exchange(node, proj);
952 static ir_node *gen_node_for_StackParam(mips_transform_env_t *env)
954 ir_node *node = env->irn;
955 ir_node *sp = get_irn_n(node, 0);
957 ir_node *nomem = new_rd_NoMem(env->irg);
961 load = new_rd_mips_load_r(env->dbg, env->irg, env->block, nomem, sp, mode_T);
962 attr = get_mips_attr(load);
963 attr->stack_entity = be_get_frame_entity(node);
964 attr->modes.load_store_mode = env->mode;
966 proj = new_rd_Proj(env->dbg, env->irg, env->block, load, env->mode, pn_Load_res);
971 static ir_node *gen_node_for_AddSP(mips_transform_env_t *env)
973 ir_node *node = env->irn;
976 const arch_register_t *reg;
978 op1 = get_irn_n(node, 0);
979 op2 = get_irn_n(node, 1);
981 add = new_rd_mips_addu(env->dbg, env->irg, env->block, op1, op2);
983 /* copy the register requirements from the old node to the new node */
984 reg = arch_get_irn_register(env->cg->arch_env, node);
985 arch_set_irn_register(env->cg->arch_env, add, reg);
990 /*********************************************************
993 * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
994 * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
995 * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
996 * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
998 *********************************************************/
1002 * Transforms the given firm node (and maybe some other related nodes)
1003 * into one or more assembler nodes.
1005 * @param node the firm node
1006 * @param env the debug module
1008 void mips_transform_node(ir_node *node, void *env) {
1009 mips_code_gen_t *cgenv = (mips_code_gen_t *)env;
1010 ir_opcode code = get_irn_opcode(node);
1011 ir_node *asm_node = node;
1012 mips_transform_env_t tenv;
1017 tenv.block = get_nodes_block(node);
1018 tenv.dbg = get_irn_dbg_info(node);
1019 tenv.irg = current_ir_graph;
1021 DEBUG_ONLY(tenv.mod = cgenv->mod;)
1022 tenv.mode = get_irn_mode(node);
1025 #define UNOP(firm_opcode, mips_nodetype) case iro_##firm_opcode: asm_node = mips_gen_##mips_nodetype(&tenv, get_##firm_opcode##_op(node)); break
1026 #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
1027 #define IGN(a) case iro_##a: break
1028 #define BAD(a) case iro_##a: goto bad
1030 DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
1044 asm_node = gen_node_for_Abs(&tenv);
1048 asm_node = gen_node_for_Rot(&tenv);
1052 asm_node = gen_node_for_Div(&tenv);
1056 asm_node = gen_node_for_Mod(&tenv);
1060 asm_node = gen_node_for_Load(&tenv);
1064 asm_node = gen_node_for_Store(&tenv);
1068 asm_node = gen_node_for_Proj(&tenv);
1072 asm_node = gen_node_for_Conv(&tenv);
1076 asm_node = gen_node_for_DivMod(&tenv);
1080 asm_node = gen_node_for_Mul(&tenv);
1084 asm_node = gen_node_for_Jmp(&tenv);
1088 asm_node = gen_node_for_IJmp(&tenv);
1092 asm_node = gen_node_for_Unknown(&tenv);
1096 asm_node = gen_node_for_Cond(&tenv);
1099 /* TODO: implement these nodes */
1102 /* You probably don't need to handle the following nodes */
1104 // call is handled in the emit phase
1106 // Cmp is handled together with Cond
1136 if(be_is_StackParam(node)) {
1137 asm_node = gen_node_for_StackParam(&tenv);
1138 } else if(be_is_AddSP(node)) {
1139 asm_node = gen_node_for_AddSP(&tenv);
1144 fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
1148 if (asm_node != node) {
1149 exchange(node, asm_node);
1150 DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1152 DB((tenv.mod, LEVEL_1, "ignored\n"));
1156 void mips_pre_transform_node(ir_node *node, void *env) {
1157 mips_code_gen_t *cgenv = (mips_code_gen_t *)env;
1160 mips_transform_env_t tenv;
1165 tenv.block = get_nodes_block(node);
1166 tenv.dbg = get_irn_dbg_info(node);
1167 tenv.irg = current_ir_graph;
1169 DEBUG_ONLY(tenv.mod = cgenv->mod;)
1170 tenv.mode = get_irn_mode(node);
1174 ir_node* pred = get_Proj_pred(node);
1176 if(get_irn_opcode(pred) == iro_CopyB) {
1177 mips_fix_CopyB_Proj(&tenv);
1181 for(i = 0; i < get_irn_arity(node); ++i) {
1182 ir_node* pred = get_irn_n(node, i);
1184 if (is_Const(pred)) {
1185 ir_node* constnode = exchange_node_for_Const(&tenv, pred, i);
1186 set_irn_n(node, i, constnode);
1187 } else if (get_irn_op(pred) == op_SymConst) {
1188 ir_node* constnode = gen_node_for_SymConst(&tenv, pred, i);
1189 set_irn_n(node, i, constnode);
1195 * Calls the transform functions for Spill and Reload.
1197 void mips_after_ra_walker(ir_node *node, void *env) {
1198 mips_code_gen_t *cg = env;
1199 mips_transform_env_t tenv;
1204 tenv.block = get_nodes_block(node);
1205 tenv.dbg = get_irn_dbg_info(node);
1206 tenv.irg = current_ir_graph;
1208 DEBUG_ONLY(tenv.mod = cg->mod;)
1209 tenv.mode = get_irn_mode(node);
1212 /* be_is_StackParam(node) || */
1213 if (be_is_Reload(node)) {
1214 mips_transform_Reload(&tenv);
1215 } else if (be_is_Spill(node)) {
1216 mips_transform_Spill(&tenv);