1 /* The codegenrator (transform FIRM into mips FIRM */
11 #include "irgraph_t.h"
21 #include "../benode_t.h"
23 #include "../besched.h"
24 #include "../besched_t.h"
25 #include "bearch_mips_t.h"
27 #include "mips_nodes_attr.h"
28 #include "../arch/archop.h" /* we need this for Min and Max nodes */
29 #include "mips_transform.h"
30 #include "mips_new_nodes.h"
31 #include "mips_map_regs.h"
32 #include "mips_util.h"
33 #include "mips_emitter.h"
35 #include "gen_mips_regalloc_if.h"
37 /****************************************************************************************************
39 * | | | | / _| | | (_)
40 * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
41 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
42 * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
43 * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
45 ****************************************************************************************************/
47 #define MIPS_GENBINFUNC(mips_nodetype) \
48 static ir_node* mips_gen_##mips_nodetype(mips_transform_env_t *env, ir_node *op1, ir_node *op2) {\
49 ASSERT_NO_FLOAT(env->mode); \
50 /*assert(get_irn_mode(op1) == get_irn_mode(op2));*/ \
51 /*assert(get_irn_mode(op1) == env->mode);*/ \
52 assert(get_mode_size_bits(env->mode) == 32); \
53 return new_rd_mips_##mips_nodetype(env->dbg, env->irg, env->block, op1, op2, env->mode);\
66 #define MIPS_GENUNFUNC(mips_nodetype) \
67 static ir_node *mips_gen_##mips_nodetype(mips_transform_env_t *env, ir_node *op) { \
68 ASSERT_NO_FLOAT(env->mode); \
69 assert(get_irn_mode(op) == env->mode); \
70 assert(get_mode_size_bits(env->mode) == 32); \
71 return new_rd_mips_##mips_nodetype(env->dbg, env->irg, env->block, op, env->mode); \
76 static ir_node* mips_get_reg_node(mips_transform_env_t *env, const arch_register_t *reg) {
77 return be_abi_get_callee_save_irn(env->cg->birg->abi, reg);
80 static ir_node* gen_zero_node(mips_transform_env_t *env, dbg_info *ebg, ir_graph *irg, ir_node *block)
82 ir_node *zero = be_abi_get_callee_save_irn(env->cg->birg->abi, &mips_general_purpose_regs[REG_ZERO]);
83 // TODO make zero nodes work
84 //ir_node *unknown = new_rd_mips_zero(dbg, irg, block, mode);
89 static ir_node* gen_node_for_Const(mips_transform_env_t *env, dbg_info *dbg, ir_graph *irg, ir_node *block, ir_node *constant)
91 tarval* tv = get_Const_tarval(constant);
95 ir_mode* mode = get_irn_mode(constant);
96 unsigned long val, lower, upper;
98 val = get_tarval_long(tv);
100 return gen_zero_node(env, dbg, irg, block);
102 lower = val & 0xffff;
103 upper = (val >> 16) & 0xffff;
105 ir_node *zero = gen_zero_node(env, dbg, irg, block);
106 ir_node *lli = new_rd_mips_lli(dbg, irg, block, zero, mode);
107 attr = get_mips_attr(lli);
108 attr->tv = new_tarval_from_long(val, mode);
113 lui = new_rd_mips_lui(dbg, irg, block, mode);
114 attr = get_mips_attr(lui);
115 attr->tv = new_tarval_from_long(val, mode);
120 lli = new_rd_mips_lli(dbg, irg, block, lui, mode);
121 attr = get_mips_attr(lli);
122 attr->tv = new_tarval_from_long(val, mode);
127 static ir_node* exchange_node_for_Const(mips_transform_env_t *env, ir_node* pred, int n) {
128 ir_node *node = env->irn;
129 dbg_info *dbg = get_irn_dbg_info(pred);
130 ir_graph *irg = get_irn_irg(node);
131 ir_mode* mode = get_irn_mode(pred);
134 if(get_irn_opcode(node) == iro_Phi) {
135 ir_node *phipred = get_nodes_block(node);
136 block = get_Block_cfgpred_block(phipred, n);
138 block = get_nodes_block(node);
141 return gen_node_for_Const(env, dbg, irg, block, pred);
144 static ir_node* gen_node_for_SymConst(mips_transform_env_t *env, ir_node* pred, int n) {
148 ir_node *node = env->irn;
149 dbg_info *dbg = get_irn_dbg_info(pred);
150 ir_graph *irg = get_irn_irg(node);
151 ir_mode* mode = get_irn_mode(pred);
155 ir_node *phipred = get_nodes_block(node);
156 block = get_Block_cfgpred_block(phipred, n);
158 block = get_nodes_block(node);
161 kind = get_SymConst_kind(pred);
162 if(kind == symconst_addr_ent) {
163 result = new_rd_mips_la(dbg, irg, block, mode);
164 attr = get_mips_attr(result);
165 attr->symconst_id = get_entity_ld_ident(get_SymConst_entity(pred));
167 } else if(kind == symconst_addr_name) {
168 result = new_rd_mips_la(dbg, irg, block, mode);
169 attr = get_mips_attr(result);
170 attr->symconst_id = get_SymConst_name(pred);
180 * Generates a mips node for a firm Load node
182 static ir_node *gen_node_for_Load(mips_transform_env_t *env) {
183 ir_node *node = env->irn;
184 ir_node *result = NULL;
189 ASSERT_NO_FLOAT(get_irn_mode(node));
191 mode = get_Load_mode(node);
192 assert(mode->vector_elem == 1);
193 assert(mode->sort == irms_int_number || mode->sort == irms_reference);
195 load_ptr = get_Load_ptr(node);
196 assert(get_mode_sort(mode) == irms_reference || get_mode_sort(mode) == irms_int_number);
197 result = new_rd_mips_load_r(env->dbg, env->irg, env->block,
198 get_Load_mem(node), load_ptr, get_irn_mode(node));
200 attr = get_mips_attr(result);
201 attr->tv = new_tarval_from_long(0, mode_Iu);
202 attr->modes.load_store_mode = mode;
208 * Generates a mips node for a firm Store node
210 static ir_node *gen_node_for_Store(mips_transform_env_t *env) {
211 ir_node *node = env->irn;
212 ir_node *result = NULL;
217 ASSERT_NO_FLOAT(env->mode);
219 store_ptr = get_Store_ptr(node);
220 mode = get_irn_mode(store_ptr);
221 assert(mode->vector_elem == 1);
222 assert(mode->sort == irms_int_number || mode->sort == irms_reference);
224 if(get_irn_opcode(store_ptr) == iro_SymConst) {
225 result = new_rd_mips_store_i(env->dbg, env->irg, env->block, get_Store_mem(node),
226 get_Store_ptr(node), get_Store_value(node), env->mode);
228 result = new_rd_mips_store_r(env->dbg, env->irg, env->block, get_Store_mem(node),
229 get_Store_ptr(node), get_Store_value(node), env->mode);
231 attr = get_mips_attr(result);
232 attr->tv = new_tarval_from_long(0, mode_Iu);
233 attr->modes.load_store_mode = mode;
238 static ir_node *gen_node_for_div_Proj(mips_transform_env_t *env) {
239 ir_node *proj = env->irn;
241 ir_node *pred = get_irn_n(proj, 0);
245 n = get_Proj_proj(proj);
247 // set the div mode to the DivMod node
248 attr = get_mips_attr(pred);
249 assert(attr->modes.original_mode == NULL || attr->modes.original_mode == env->mode);
250 attr->modes.original_mode = env->mode;
252 // we have to construct a new proj here, to avoid circular refs that
253 // happen when we reuse the old one
254 new_proj = new_ir_node(env->dbg, env->irg, env->block, op_Proj, mode_ANY, 1, &pred);
255 set_Proj_proj(new_proj, n);
257 if(n == pn_DivMod_res_div) {
258 return new_rd_mips_mflo(env->dbg, env->irg, env->block, new_proj, env->mode);
259 } else if(n == pn_DivMod_res_mod) {
260 return new_rd_mips_mfhi(env->dbg, env->irg, env->block, new_proj, env->mode);
266 static ir_node *make_jmp_or_fallthrough(mips_transform_env_t *env)
268 const ir_edge_t *edge;
269 ir_node *node = env->irn;
271 int our_block_sched_nr = mips_get_block_sched_nr(get_nodes_block(node));
273 edge = get_irn_out_edge_first(node);
274 next_block = get_edge_src_irn(edge);
276 if(mips_get_sched_block(env->cg, our_block_sched_nr + 1) == next_block) {
277 return new_rd_mips_fallthrough(env->dbg, env->irg, env->block, mode_X);
280 return new_rd_mips_b(env->dbg, env->irg, env->block, mode_X);
283 static ir_node *gen_node_for_Cond_Proj(mips_transform_env_t *env, ir_node* node, int true_false)
285 // we can't use get_Cond_selector here because the selector is already
286 // replaced by a mips_ compare node
287 ir_node *proj = get_Cond_selector(node);
288 ir_node *original_cmp = get_irn_n(proj, 0);
289 ir_node *result = NULL;
293 dbg_info *dbg = env->dbg;
294 ir_graph *irg = env->irg;
295 ir_node *block = env->block;
298 n = get_Proj_proj(proj);
299 assert(n < 8 && "Only ordered comps supported");
301 assert(get_irn_opcode(original_cmp) == iro_Cmp);
302 op1 = get_Cmp_left(original_cmp);
303 op2 = get_Cmp_right(original_cmp);
310 return make_jmp_or_fallthrough(env);
314 return make_jmp_or_fallthrough(env);
316 condjmp = new_rd_mips_beq(dbg, irg, block, op1, op2, mode_T);
317 return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
321 return make_jmp_or_fallthrough(env);
323 cmp = new_rd_mips_slt(dbg, irg, block, op1, op2, get_irn_mode(op1));
324 condjmp = new_rd_mips_bgtz(dbg, irg, block, cmp, mode_T);
325 return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
329 return make_jmp_or_fallthrough(env);
331 cmp = new_rd_mips_slt(dbg, irg, block, op2, op1, get_irn_mode(op1));
332 condjmp = new_rd_mips_blez(dbg, irg, block, cmp, mode_T);
333 return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
337 return make_jmp_or_fallthrough(env);
339 cmp = new_rd_mips_slt(dbg, irg, block, op2, op1, get_irn_mode(op1));
340 condjmp = new_rd_mips_bgtz(dbg, irg, block, cmp, mode_T);
341 return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
345 return make_jmp_or_fallthrough(env);
347 cmp = new_rd_mips_slt(dbg, irg, block, op1, op2, get_irn_mode(op1));
348 condjmp = new_rd_mips_blez(dbg, irg, block, cmp, mode_T);
349 return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
353 return make_jmp_or_fallthrough(env);
355 condjmp = new_rd_mips_bne(dbg, irg, block, op1, op2, mode_T);
356 return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
362 return make_jmp_or_fallthrough(env);
371 static ir_node *gen_node_for_Proj(mips_transform_env_t *env)
373 ir_node *proj = env->irn;
375 ir_node *predecessor = get_Proj_pred(proj);
377 // all DivMods, Div, Mod should be replaced by now
378 assert(get_irn_opcode(predecessor) != iro_DivMod);
379 assert(get_irn_opcode(predecessor) != iro_Div);
380 assert(get_irn_opcode(predecessor) != iro_Mod);
382 if(is_mips_div(predecessor))
383 return gen_node_for_div_Proj(env);
385 if(get_irn_opcode(predecessor) == iro_Cond) {
386 ir_node *selector = get_Cond_selector(predecessor);
387 ir_mode *mode = get_irn_mode(selector);
388 n = get_Proj_proj(proj);
390 if(get_mode_sort(mode) == irms_internal_boolean) {
391 assert(n == pn_Cond_true || n == pn_Cond_false);
392 return gen_node_for_Cond_Proj(env, predecessor, n == pn_Cond_true);
399 static ir_node *gen_node_for_Cond(mips_transform_env_t *env)
401 ir_node *selector = get_Cond_selector(env->irn);
402 ir_mode *selector_mode = get_irn_mode(selector);
403 ir_node *node = env->irn;
404 dbg_info *dbg = env->dbg;
405 ir_graph *irg = env->irg;
406 ir_node *block = env->block;
407 ir_node *sub, *sltu, *minval_const, *max_const, *switchjmp;
408 ir_node *defaultproj, *defaultproj_succ;
410 long pn, minval, maxval, defaultprojn;
411 const ir_edge_t *edge;
412 ir_node *zero, *two_const, *add, *la, *load, *proj;
413 ir_mode *unsigned_mode;
416 // mode_b conds are handled by gen_node_for_Proj
417 if(get_mode_sort(selector_mode) != irms_int_number)
420 assert(get_mode_size_bits(selector_mode) == 32);
422 defaultprojn = get_Cond_defaultProj(node);
424 // go over all projs to find min-&maxval of the switch
427 foreach_out_edge(node, edge) {
428 ir_node* proj = get_edge_src_irn(edge);
429 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
431 pn = get_Proj_proj(proj);
432 if(pn == defaultprojn) {
442 assert(defaultproj != NULL);
444 // subtract minval from the switch value
447 minval_const = new_rd_Const(dbg, irg, block, selector_mode, new_tarval_from_long(minval, selector_mode));
448 minval_const = gen_node_for_Const(env, dbg, irg, block, minval_const);
449 sub = new_rd_mips_sub(dbg, irg, block, selector, minval_const, selector_mode);
454 // compare if we're above maxval-minval or below zero.
455 // we can do this with 1 compare because we use unsigned mode
456 unsigned_mode = new_ir_mode(get_mode_name(selector_mode),
457 get_mode_sort(selector_mode), get_mode_size_bits(selector_mode),
458 0, get_mode_arithmetic(selector_mode), get_mode_modulo_shift(selector_mode));
460 max_const = new_rd_Const(dbg, irg, block, unsigned_mode, new_tarval_from_long(maxval - minval + 1, unsigned_mode));
461 max_const = gen_node_for_Const(env, dbg, irg, block, max_const);
462 sltu = new_rd_mips_slt(dbg, irg, block, sub, max_const, unsigned_mode);
464 zero = gen_zero_node(env, dbg, irg, block);
465 beq = new_rd_mips_beq(dbg, irg, block, sltu, zero, mode_T);
467 // attach defaultproj to beq now
468 set_irn_n(defaultproj, 0, beq);
469 set_Proj_proj(defaultproj, 1);
471 two_const = new_rd_Const(dbg, irg, block, unsigned_mode, new_tarval_from_long(2, unsigned_mode));
472 two_const = gen_node_for_Const(env, dbg, irg, block, two_const);
473 sl = new_rd_mips_sl(dbg, irg, block, sub, two_const, unsigned_mode);
475 la = new_rd_mips_la(dbg, irg, block, mode_Iu);
476 add = new_rd_mips_add(dbg, irg, block, sl, la, mode_Iu);
477 load = new_rd_mips_load_r(dbg, irg, block, new_rd_NoMem(irg), add, mode_T);
478 attr = get_mips_attr(load);
479 attr->modes.load_store_mode = mode_Iu;
480 attr->tv = new_tarval_from_long(0, mode_Iu);
482 proj = new_rd_Proj(dbg, irg, block, load, mode_Iu, pn_Load_res);
484 switchjmp = new_rd_mips_SwitchJump(dbg, irg, block, proj, mode_T);
485 attr = get_mips_attr(switchjmp);
486 attr->switch_default_pn = defaultprojn;
488 edge = get_irn_out_edge_first(defaultproj);
489 defaultproj_succ = get_edge_src_irn(edge);
490 attr->symconst_id = new_id_from_str(mips_get_block_label(defaultproj_succ));
492 attr = get_mips_attr(la);
493 attr->symconst_id = new_id_from_str(mips_get_jumptbl_label(switchjmp));
498 static ir_node *create_conv_store_load(mips_transform_env_t *env, ir_mode* srcmode, ir_mode* dstmode) {
499 ir_node *nomem, *store, *mem_proj, *value_proj, *load;
501 ir_node *node = env->irn;
502 ir_node *pred = get_Conv_op(node);
504 // TODO HACK make this global...
507 ir_type *ptr_i32type;
510 id = new_id_from_str("__conv0");
511 i32type = new_type_primitive(new_id_from_str("ptr32"), mode_Iu);
512 ptr_i32type = new_d_type_pointer(id, i32type, mode_P, env->dbg);
513 mem_entity = new_d_entity(get_irg_frame_type(env->irg), id, ptr_i32type, env->dbg);
515 sp = mips_get_reg_node(env, &mips_general_purpose_regs[REG_SP]);
516 nomem = new_ir_node(env->dbg, env->irg, env->block, op_NoMem, mode_M, 0, NULL);
518 store = new_rd_mips_store_r(env->dbg, env->irg, env->block, nomem, sp, pred, mode_T);
519 attr = get_mips_attr(store);
520 attr->tv = new_tarval_from_long(0, mode_Iu);
521 attr->modes.load_store_mode = srcmode;
522 attr->stack_entity = mem_entity;
524 mem_proj = new_ir_node(env->dbg, env->irg, env->block, op_Proj, mode_M, 1, &store);
525 set_Proj_proj(mem_proj, pn_Store_M);
527 load = new_rd_mips_load_r(env->dbg, env->irg, env->block, mem_proj, sp, mode_T);
528 attr = get_mips_attr(load);
529 attr->tv = new_tarval_from_long(0, mode_Iu);
530 attr->modes.load_store_mode = dstmode;
531 attr->stack_entity = mem_entity;
533 value_proj = new_ir_node(env->dbg, env->irg, env->block, op_Proj, env->mode, 1, &load);
534 set_Proj_proj(value_proj, pn_Load_res);
539 static ir_node *create_conv_and(mips_transform_env_t *env, long immediate) {
540 ir_node *node = env->irn;
545 pred = get_Conv_op(node);
546 result = new_rd_mips_andi(env->dbg, env->irg, env->block, pred, node->mode);
547 attr = get_mips_attr(result);
548 attr->tv = new_tarval_from_long(immediate, mode_Iu);
553 static ir_node *gen_node_for_Conv(mips_transform_env_t *env) {
554 ir_node *node = env->irn;
558 int dst_size, src_size;
560 pred = get_Conv_op(node);
561 srcmode = get_irn_mode(pred);
562 destmode = get_irn_mode(node);
564 dst_size = get_mode_size_bits(destmode);
565 src_size = get_mode_size_bits(srcmode);
567 if(srcmode->size >= destmode->size) {
568 assert(srcmode->size > destmode->size || srcmode->sign != destmode->sign);
569 return new_rd_mips_reinterpret_conv(env->dbg, env->irg, env->block, pred, node->mode);
572 if(srcmode->size == 8) {
573 return create_conv_store_load(env, mode_Bs, mode_Bs);
574 } else if(srcmode->size == 16) {
575 return create_conv_store_load(env, mode_Hs, mode_Hs);
579 return create_conv_and(env, 0xff);
580 } else if(src_size == 16) {
581 return create_conv_and(env, 0xffff);
589 static ir_node *gen_node_mips_div(mips_transform_env_t *env, ir_node* op1, ir_node* op2, long p_div, long p_mod,
592 ir_node *node = env->irn;
594 const ir_edge_t *edge;
596 div = new_rd_mips_div(env->dbg, env->irg, env->block, op1, op2, mode_T);
599 foreach_out_edge(node, edge) {
600 ir_node *proj = get_edge_src_irn(edge);
601 long n = get_Proj_proj(proj);
602 assert(is_Proj(proj) && "non-Proj from Mod node");
604 set_Proj_proj(proj, pn_DivMod_res_div);
605 } else if (n == p_mod) {
606 set_Proj_proj(proj, pn_DivMod_res_mod);
607 } else if(n == p_m) {
608 set_Proj_proj(proj, pn_DivMod_M);
609 } else if(n == p_x) {
610 set_Proj_proj(proj, pn_DivMod_X_except);
612 assert(!"invalid proj");
619 static ir_node *gen_node_for_DivMod(mips_transform_env_t *env) {
620 ir_node *node = env->irn;
622 return gen_node_mips_div(env, get_DivMod_left(node), get_DivMod_right(node), pn_DivMod_res_div,
623 pn_DivMod_res_mod, pn_DivMod_M, pn_DivMod_X_except);
626 static ir_node *gen_node_for_Div(mips_transform_env_t *env) {
627 ir_node *node = env->irn;
629 return gen_node_mips_div(env, get_Div_left(node), get_Div_right(node), pn_Div_res, -1,
630 pn_Div_M, pn_Div_X_except);
633 static ir_node *gen_node_for_Mod(mips_transform_env_t *env) {
634 ir_node *node = env->irn;
636 return gen_node_mips_div(env, get_Mod_left(node), get_Mod_right(node), -1, pn_Mod_res,
637 pn_Mod_M, pn_Mod_X_except);
640 static ir_node *gen_node_for_Mul(mips_transform_env_t *env) {
641 ir_node *node = env->irn;
646 op1 = get_Mul_left(node);
647 op2 = get_Mul_right(node);
649 assert(get_mode_size_bits(env->mode) == 32);
650 assert(get_mode_size_bits(get_irn_mode(op1)) == get_mode_size_bits(env->mode));
651 assert(get_mode_size_bits(get_irn_mode(op2)) == get_mode_size_bits(env->mode));
653 mul = new_rd_mips_mult(env->dbg, env->irg, env->block, get_Mul_left(node), get_Mul_right(node), env->mode);
654 mflo = new_rd_mips_mflo(env->dbg, env->irg, env->block, mul, env->mode);
659 static ir_node *gen_node_for_IJmp(mips_transform_env_t *env) {
660 ir_node *node = env->irn;
662 return new_rd_mips_j(env->dbg, env->irg, env->block, get_IJmp_target(node), node->mode);
665 static ir_node *gen_node_for_Jmp(mips_transform_env_t *env) {
666 return make_jmp_or_fallthrough(env);
669 static ir_node *gen_node_for_Abs(mips_transform_env_t *env) {
670 ir_node *node = env->irn;
671 ir_node *sra, *add, *xor;
674 // TODO for other bit sizes...
675 assert(get_mode_size_bits(env->mode) == 32);
676 sra = new_rd_mips_srai(env->dbg, env->irg, env->block, get_Abs_op(node), node->mode);
677 attr = get_mips_attr(sra);
678 attr->tv = new_tarval_from_long(31, mode_Iu);
679 add = new_rd_mips_add(env->dbg, env->irg, env->block, get_Abs_op(node), sra, node->mode);
680 xor = new_rd_mips_xor(env->dbg, env->irg, env->block, sra, add, node->mode);
685 static ir_node *gen_node_for_Rot(mips_transform_env_t *env) {
686 ir_node *node = env->irn;
687 ir_node *subu, *srlv, *sllv, *or;
689 subu = new_rd_mips_subuzero(env->dbg, env->irg, env->block, get_Rot_right(node), env->mode);
690 srlv = new_rd_mips_srlv(env->dbg, env->irg, env->block, get_Rot_left(node), subu, env->mode);
691 sllv = new_rd_mips_sllv(env->dbg, env->irg, env->block, get_Rot_left(node), get_Rot_right(node), env->mode);
692 or = new_rd_mips_or(env->dbg, env->irg, env->block, sllv, srlv, env->mode);
697 static ir_node *gen_node_for_Unknown(mips_transform_env_t *env)
699 return gen_zero_node(env, env->dbg, env->irg, env->block);
703 * lower a copyB into standard Firm assembler :-)
705 ir_node *gen_code_for_CopyB(ir_node *block, ir_node *node) {
707 ir_node *dst = get_CopyB_dst(node);
708 ir_node *src = get_CopyB_src(node);
709 ir_type *type = get_CopyB_type(node);
710 ir_node *mem = get_CopyB_mem(node);
712 ir_node *result = NULL;
713 int size = get_type_size_bytes(type);
714 dbg_info *dbg = get_irn_dbg_info(node);
715 ir_graph *irg = get_irn_irg(block);
720 ir_node *phi, *projT, *projF, *cmp, *proj, *cond, *jmp, *in[2];
721 ir_node *new_bl, *src_phi, *dst_phi, *mem_phi, *add;
722 ir_mode *p_mode = get_irn_mode(src);
725 /* build the control loop */
726 in[0] = in[1] = new_r_Unknown(irg, mode_X);
728 new_bl = new_r_Block(irg, 2, in);
730 in[0] = cnt = new_Const_long(mode_Is, (size >> 4));
731 in[1] = new_r_Unknown(irg, mode_Is);
732 phi = new_r_Phi(irg, new_bl, 2, in, mode_Is);
734 sub = new_rd_Sub(dbg, irg, new_bl, phi, new_Const_long(mode_Is, -1), mode_Is);
735 set_Phi_pred(phi, 1, sub);
737 cmp = new_rd_Cmp(dbg, irg, new_bl, sub, new_Const_long(mode_Is, 0));
738 proj = new_r_Proj(irg, new_bl, cmp, mode_b, pn_Cmp_Lg);
739 cond = new_rd_Cond(dbg, irg, new_bl, proj);
741 projT = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_true);
742 projF = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_false);
744 jmp = get_Block_cfgpred(block, 0);
745 set_Block_cfgpred(block, 0, projF);
747 set_Block_cfgpred(new_bl, 0, jmp);
748 set_Block_cfgpred(new_bl, 1, projT);
754 in[1] = new_r_Unknown(irg, p_mode);
755 src_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
758 dst_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
760 add = new_rd_Add(dbg, irg, new_bl, src_phi, new_Const_long(mode_Is, 16), p_mode);
761 set_Phi_pred(src_phi, 1, add);
762 add = new_rd_Add(dbg, irg, new_bl, dst_phi, new_Const_long(mode_Is, 16), p_mode);
763 set_Phi_pred(dst_phi, 1, add);
766 in[1] = new_r_Unknown(irg, mode_M);
767 mem_phi = new_r_Phi(irg, new_bl, 2, in, mode_M);
772 /* create 4 parallel loads */
773 for (i = 0; i < 4; ++i) {
776 load = new_rd_mips_load_r(dbg, irg, new_bl, mem_phi, src, mode_T);
777 attr = get_mips_attr(load);
778 attr->modes.load_store_mode = mode_Iu;
779 attr->tv = new_tarval_from_long(i * 4, mode_Iu);
781 ld[i] = new_rd_Proj(dbg, irg, new_bl, load, mode_Iu, pn_Load_res);
784 /* create 4 parallel stores */
785 for (i = 0; i < 4; ++i) {
788 store = new_rd_mips_store_r(dbg, irg, new_bl, mem_phi, dst, ld[i], mode_T);
789 attr = get_mips_attr(store);
790 attr->modes.load_store_mode = mode_Iu;
791 attr->tv = new_tarval_from_long(i * 4, mode_Iu);
793 mm[i] = new_rd_Proj(dbg, irg, new_bl, store, mode_M, pn_Store_M);
795 mem = new_r_Sync(irg, new_bl, 4, mm);
797 set_Phi_pred(mem_phi, 1, mem);
800 // output store/loads manually
802 for(i = size; i > 0; ) {
804 ir_node *load, *store, *projv;
805 int offset = size - i;
817 load = new_rd_mips_load_r(dbg, irg, block, mem, src, mode_T);
818 attr = get_mips_attr(load);
819 attr->modes.load_store_mode = mode;
820 attr->tv = new_tarval_from_long(offset, mode_Iu);
822 projv = new_rd_Proj(dbg, irg, block, load, mode, pn_Load_res);
824 store = new_rd_mips_store_r(dbg, irg, block, mem, dst, projv, mode_T);
825 attr = get_mips_attr(store);
826 attr->modes.load_store_mode = mode;
827 attr->tv = new_tarval_from_long(offset, mode_Iu);
829 mm[n] = new_rd_Proj(dbg, irg, block, store, mode_M, pn_Store_M);
834 result = new_r_Sync(irg, block, n, mm);
842 static void mips_fix_CopyB_Proj(mips_transform_env_t* env) {
843 ir_node *node = env->irn;
844 long n = get_Proj_proj(node);
846 if(n == pn_CopyB_M_except) {
848 } else if(n == pn_CopyB_M_regular) {
849 set_Proj_proj(node, pn_Store_M);
850 } else if(n == pn_CopyB_M_except) {
851 set_Proj_proj(node, pn_Store_X_except);
855 static void mips_transform_Spill(mips_transform_env_t* env) {
856 ir_node *node = env->irn;
857 ir_node *sched_point = NULL;
858 ir_node *store, *proj;
859 ir_node *nomem = new_rd_NoMem(env->irg);
860 ir_node *ptr = get_irn_n(node, 0);
861 ir_node *val = get_irn_n(node, 1);
862 entity *ent = be_get_frame_entity(node);
865 if(sched_is_scheduled(node)) {
866 sched_point = sched_prev(node);
869 store = new_rd_mips_store_r(env->dbg, env->irg, env->block, nomem, ptr, val, mode_T);
870 attr = get_mips_attr(store);
871 attr->stack_entity = ent;
872 attr->modes.load_store_mode = get_irn_mode(val);
874 proj = new_rd_Proj(env->dbg, env->irg, env->block, store, mode_M, pn_Store_M);
877 sched_add_after(sched_point, store);
878 sched_add_after(store, proj);
883 exchange(node, proj);
886 static void mips_transform_Reload(mips_transform_env_t* env) {
887 ir_node *node = env->irn;
888 ir_node *sched_point = NULL;
889 ir_node *load, *proj;
890 ir_node *nomem = new_rd_NoMem(env->irg);
891 ir_node *ptr = get_irn_n(node, 0);
892 ir_node *mem = get_irn_n(node, 1);
893 ir_mode *mode = get_irn_mode(node);
894 entity *ent = be_get_frame_entity(node);
895 const arch_register_t* reg;
898 if(sched_is_scheduled(node)) {
899 sched_point = sched_prev(node);
902 load = new_rd_mips_load_r(env->dbg, env->irg, env->block, mem, ptr, mode_T);
903 attr = get_mips_attr(load);
904 attr->stack_entity = ent;
905 attr->modes.load_store_mode = mode;
907 proj = new_rd_Proj(env->dbg, env->irg, env->block, load, mode, pn_Load_res);
910 sched_add_after(sched_point, load);
911 sched_add_after(load, proj);
916 /* copy the register from the old node to the new Load */
917 reg = arch_get_irn_register(env->cg->arch_env, node);
918 arch_set_irn_register(env->cg->arch_env, proj, reg);
920 exchange(node, proj);
923 static ir_node *gen_node_for_StackParam(mips_transform_env_t *env)
925 ir_node *node = env->irn;
926 ir_node *sp = get_irn_n(node, 0);
928 ir_node *nomem = new_rd_NoMem(env->irg);
932 load = new_rd_mips_load_r(env->dbg, env->irg, env->block, nomem, sp, mode_T);
933 attr = get_mips_attr(load);
934 attr->stack_entity = be_get_frame_entity(node);
935 attr->modes.load_store_mode = env->mode;
937 proj = new_rd_Proj(env->dbg, env->irg, env->block, load, env->mode, pn_Load_res);
942 static ir_node *gen_node_for_AddSP(mips_transform_env_t *env)
944 ir_node *node = env->irn;
947 const arch_register_t *reg;
949 op1 = get_irn_n(node, 0);
950 op2 = get_irn_n(node, 1);
952 add = new_rd_mips_add(env->dbg, env->irg, env->block, op1, op2, mode_Iu);
954 /* copy the register requirements from the old node to the new node */
955 reg = arch_get_irn_register(env->cg->arch_env, node);
956 arch_set_irn_register(env->cg->arch_env, add, reg);
961 /*********************************************************
964 * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
965 * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
966 * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
967 * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
969 *********************************************************/
973 * Transforms the given firm node (and maybe some other related nodes)
974 * into one or more assembler nodes.
976 * @param node the firm node
977 * @param env the debug module
979 void mips_transform_node(ir_node *node, void *env) {
980 mips_code_gen_t *cgenv = (mips_code_gen_t *)env;
981 opcode code = get_irn_opcode(node);
982 ir_node *asm_node = node;
983 mips_transform_env_t tenv;
988 tenv.block = get_nodes_block(node);
989 tenv.dbg = get_irn_dbg_info(node);
990 tenv.irg = current_ir_graph;
992 tenv.mod = cgenv->mod;
993 tenv.mode = get_irn_mode(node);
996 #define UNOP(firm_opcode, mips_nodetype) case iro_##firm_opcode: asm_node = mips_gen_##mips_nodetype(&tenv, get_##firm_opcode##_op(node)); break
997 #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
998 #define IGN(a) case iro_##a: break
999 #define BAD(a) case iro_##a: goto bad
1001 DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
1015 asm_node = gen_node_for_Abs(&tenv);
1019 asm_node = gen_node_for_Rot(&tenv);
1023 asm_node = gen_node_for_Div(&tenv);
1027 asm_node = gen_node_for_Mod(&tenv);
1031 asm_node = gen_node_for_Load(&tenv);
1035 asm_node = gen_node_for_Store(&tenv);
1039 asm_node = gen_node_for_Proj(&tenv);
1043 asm_node = gen_node_for_Conv(&tenv);
1047 asm_node = gen_node_for_DivMod(&tenv);
1051 asm_node = gen_node_for_Mul(&tenv);
1055 asm_node = gen_node_for_Jmp(&tenv);
1059 asm_node = gen_node_for_IJmp(&tenv);
1063 asm_node = gen_node_for_Unknown(&tenv);
1067 asm_node = gen_node_for_Cond(&tenv);
1070 /* TODO: implement these nodes */
1073 /* You probably don't need to handle the following nodes */
1075 // call is handled in the emit phase
1077 // Cmp is handled together with Cond
1107 if(be_is_StackParam(node)) {
1108 asm_node = gen_node_for_StackParam(&tenv);
1109 } else if(be_is_AddSP(node)) {
1110 asm_node = gen_node_for_AddSP(&tenv);
1115 fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
1119 if (asm_node != node) {
1120 exchange(node, asm_node);
1121 DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1123 DB((tenv.mod, LEVEL_1, "ignored\n"));
1127 void mips_pre_transform_node(ir_node *node, void *env) {
1128 mips_code_gen_t *cgenv = (mips_code_gen_t *)env;
1131 mips_transform_env_t tenv;
1136 tenv.block = get_nodes_block(node);
1137 tenv.dbg = get_irn_dbg_info(node);
1138 tenv.irg = current_ir_graph;
1140 tenv.mod = cgenv->mod;
1141 tenv.mode = get_irn_mode(node);
1145 ir_node* pred = get_Proj_pred(node);
1147 if(get_irn_opcode(pred) == iro_CopyB) {
1148 mips_fix_CopyB_Proj(&tenv);
1152 for(i = 0; i < get_irn_arity(node); ++i) {
1153 ir_node* pred = get_irn_n(node, i);
1155 if (is_Const(pred)) {
1156 ir_node* constnode = exchange_node_for_Const(&tenv, pred, i);
1157 set_irn_n(node, i, constnode);
1158 } else if (get_irn_op(pred) == op_SymConst) {
1159 ir_node* constnode = gen_node_for_SymConst(&tenv, pred, i);
1160 set_irn_n(node, i, constnode);
1166 * Calls the transform functions for Spill and Reload.
1168 void mips_after_ra_walker(ir_node *node, void *env) {
1169 mips_code_gen_t *cg = env;
1170 mips_transform_env_t tenv;
1175 tenv.block = get_nodes_block(node);
1176 tenv.dbg = get_irn_dbg_info(node);
1177 tenv.irg = current_ir_graph;
1180 tenv.mode = get_irn_mode(node);
1183 /* be_is_StackParam(node) || */
1184 if (be_is_Reload(node)) {
1185 mips_transform_Reload(&tenv);
1186 } else if (be_is_Spill(node)) {
1187 mips_transform_Spill(&tenv);