1 /* The codegenrator (transform FIRM into arm FIRM */
20 #include "../benode_t.h"
21 #include "bearch_arm_t.h"
23 #include "arm_nodes_attr.h"
24 #include "../arch/archop.h" /* we need this for Min and Max nodes */
25 #include "arm_transform.h"
26 #include "arm_new_nodes.h"
27 #include "arm_map_regs.h"
29 #include "gen_arm_regalloc_if.h"
34 extern ir_op *get_op_Mulh(void);
38 /****************************************************************************************************
40 * | | | | / _| | | (_)
41 * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
42 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
43 * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
44 * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
46 ****************************************************************************************************/
49 static unsigned do_rol(unsigned v, unsigned rol)
51 return (v << rol) | (v >> (32 - rol));
54 typedef struct vals_ {
56 unsigned char values[4];
57 unsigned char shifts[4];
60 static void gen_vals_from_word(unsigned int value, vals *result)
64 memset(result, 0, sizeof(*result));
66 /* special case: we prefer shift amount 0 */
68 result->values[0] = value;
75 unsigned v = do_rol(value, 8) & 0xFFFFFF;
84 shf = (initial + shf - 8) & 0x1F;
85 result->values[result->ops] = v;
86 result->shifts[result->ops] = shf;
89 value ^= do_rol(v, shf) >> initial;
99 * Creates a arm_Const node.
101 static ir_node *create_const_node(arm_transform_env_t *env, long value) {
102 tarval *tv = new_tarval_from_long(value, mode_Iu);
103 return new_rd_arm_Mov_i(env->dbg, env->irg, env->block, env->mode, tv);
107 * Creates a arm_Const_Neg node.
109 static ir_node *create_const_neg_node(arm_transform_env_t *env, long value) {
110 tarval *tv = new_tarval_from_long(value, mode_Iu);
111 return new_rd_arm_Mvn_i(env->dbg, env->irg, env->block, env->mode, tv);
114 #define NEW_BINOP_NODE(opname, env, op1, op2) new_rd_arm_##opname(env->dbg, env->irg, env->block, op1, op2, env->mode)
117 * Encodes an immediate with shifter operand
119 static unsigned int arm_encode_imm_w_shift(unsigned int shift, unsigned int immediate) {
120 return immediate | ((shift>>1)<<8);
124 * Decode an immediate with shifter operand
126 unsigned int arm_decode_imm_w_shift(tarval *tv) {
127 unsigned l = get_tarval_long(tv);
128 unsigned rol = (l & ~0xFF) >> 7;
130 return do_rol(l & 0xFF, rol);
134 * Creates a possible DAG for an constant.
136 static ir_node *create_const_graph_value(arm_transform_env_t *env, unsigned int value) {
142 gen_vals_from_word(value, &v);
143 gen_vals_from_word(~value, &vn);
145 if (vn.ops < v.ops) {
147 result = create_const_neg_node(env, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
149 for (cnt = 1; cnt < vn.ops; ++cnt) {
150 tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]), mode_Iu);
151 ir_node *bic_i_node = new_rd_arm_Bic_i(env->dbg, env->irg, env->block, result, env->mode, tv);
157 result = create_const_node(env, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
159 for (cnt = 1; cnt < v.ops; ++cnt) {
160 tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]), mode_Iu);
161 ir_node *orr_i_node = new_rd_arm_Or_i(env->dbg, env->irg, env->block, result, env->mode, tv);
168 static ir_node *create_const_graph(arm_transform_env_t *env) {
169 int value = get_tarval_long(get_Const_tarval(env->irn));
170 return create_const_graph_value(env, value);
175 static ir_node *gen_Const(arm_transform_env_t *env) {
177 assert(env->mode != mode_E && "IEEE Extended FP not supported");
178 if (env->mode == mode_F) {
179 result = new_rd_arm_fConst(env->dbg, env->irg, env->block, env->mode);
180 get_arm_attr(result)->value = get_Const_tarval(env->irn);
181 } else if (env->mode == mode_D) {
182 result = new_rd_arm_fConst(env->dbg, env->irg, env->block, env->mode);
183 get_arm_attr(result)->value = get_Const_tarval(env->irn);
184 } else if (env->mode == mode_P) {
187 result = create_const_graph(env);
192 static ir_node *gen_mask(arm_transform_env_t *env, ir_node *op, int result_bits) {
193 unsigned mask_bits = (1 << result_bits) - 1;
194 ir_node *mask_node = create_const_graph_value(env, mask_bits);
195 return new_rd_arm_And(env->dbg, env->irg, env->block, op, mask_node, get_irn_mode(env->irn), ARM_SHF_NONE, NULL);
198 static ir_node *gen_sign_extension(arm_transform_env_t *env, ir_node *op, int result_bits) {
199 int shift_width = 32 - result_bits;
200 ir_node *shift_const_node = create_const_graph_value(env, shift_width);
201 ir_node *lshift_node = new_rd_arm_Shl(env->dbg, env->irg, env->block, op, shift_const_node, get_irn_mode(op));
202 ir_node *rshift_node = new_rd_arm_Shrs(env->dbg, env->irg, env->block, lshift_node, shift_const_node, get_irn_mode(env->irn));
207 * Transforms a Conv node.
209 * @param env The transformation environment
210 * @return the created arm Conv node
212 static ir_node *gen_Conv(arm_transform_env_t *env) {
213 ir_node *op = get_Conv_op(env->irn);
214 ir_mode *in_mode = get_irn_mode(op);
215 ir_mode *out_mode = env->mode;
217 assert( in_mode != mode_E && "");
218 assert( in_mode != mode_Ls && "");
219 assert( in_mode != mode_Lu && "");
220 assert( out_mode != mode_E && "");
221 assert( out_mode != mode_Ls && "");
222 assert( out_mode != mode_Lu && "");
224 if (in_mode == out_mode)
227 if ((mode_is_int(in_mode) || mode_is_reference(in_mode))
228 && (mode_is_reference(out_mode) || mode_is_int(out_mode))) {
229 int in_bits = get_mode_size_bits(in_mode);
230 int out_bits = get_mode_size_bits(out_mode);
231 int in_sign = get_mode_sign(in_mode);
232 int out_sign = get_mode_sign(out_mode);
236 if (in_bits == out_bits && in_bits == 32)
240 // unsigned -> unsigned
242 // unsigned -> signed
243 // sign extension (31:16)=(15)
244 // signed -> unsigned
245 // maskieren (31:16)=0
248 if (in_bits == out_bits && out_bits < 32) {
249 if (in_sign && !out_sign) {
250 return gen_mask(env, op, out_bits);
252 return gen_sign_extension(env, op, out_bits);
257 // unsigned -> unsigned
259 // unsigned -> signed
261 // signed -> unsigned
262 // sign extension (31:16)=(15)
264 // sign extension (31:16)=(15)
265 if (in_bits < out_bits) {
267 return gen_sign_extension(env, op, out_bits);
274 // unsigned -> unsigned
275 // maskieren (31:16)=0
276 // unsigned -> signed
277 // maskieren (31:16)=0
278 // signed -> unsigned
279 // maskieren (31:16)=0
281 // sign extension (erledigt auch maskieren) (31:16)=(15)
282 if (in_bits > out_bits) {
283 if (in_sign && out_sign) {
284 return gen_sign_extension(env, op, out_bits);
286 return gen_mask(env, op, out_bits);
289 assert(0 && "recheck integer conversion logic!");
291 } else if (in_mode == mode_D && out_mode == mode_F) {
292 return new_rd_arm_fConvD2S(env->dbg, env->irg, env->block, op, env->mode);
293 } else if (in_mode == mode_F && out_mode == mode_D) {
294 return new_rd_arm_fConvS2D(env->dbg, env->irg, env->block, op, env->mode);
295 } else if (mode_is_int(in_mode) && mode_is_float(out_mode)) {
296 env->cg->have_fp = 1;
297 return env->irn; /* TODO: implement int->float conversion*/
298 } else if (mode_is_float(in_mode) && mode_is_int(out_mode)) {
299 env->cg->have_fp = 1;
300 return env->irn; /* TODO: implement float->int conversion*/
302 assert(0 && "not implemented conversion");
308 * Return true if an operand is a shifter operand
310 static int is_shifter_operand(ir_node *n, arm_shift_modifier *pmod) {
311 arm_shift_modifier mod = ARM_SHF_NONE;
314 mod = get_arm_shift_modifier(n);
317 if (mod != ARM_SHF_NONE) {
318 long v = get_tarval_long(get_arm_value(n));
326 * Creates an arm Add.
328 * @param env The transformation environment
329 * @return the created arm Add node
331 static ir_node *gen_Add(arm_transform_env_t *env) {
332 ir_node *irn = env->irn;
333 ir_node *op1 = get_Add_left(irn);
334 ir_node *op2 = get_Add_right(irn);
337 arm_shift_modifier mod;
339 assert(env->mode != mode_E && "IEEE Extended FP not supported");
341 if (mode_is_float(env->mode)) {
342 env->cg->have_fp = 1;
343 return new_rd_arm_fAdd(env->dbg, env->irg, env->block, op1, op2, env->mode);
345 if (mode_is_numP(env->mode)) {
346 if (is_arm_Mov_i(op1))
347 return new_rd_arm_Add_i(env->dbg, env->irg, env->block, op2, env->mode,
349 if (is_arm_Mov_i(op2))
350 return new_rd_arm_Add_i(env->dbg, env->irg, env->block, op1, env->mode,
354 if (is_arm_Mul(op1) && get_irn_n_edges(op1) == 1) {
356 op2 = get_irn_n(op1, 1);
357 op1 = get_irn_n(op1, 0);
359 return new_rd_arm_Mla(env->dbg, env->irg, env->block, op1, op2, op3, env->mode);
361 if (is_arm_Mul(op2) && get_irn_n_edges(op2) == 1) {
363 op1 = get_irn_n(op2, 0);
364 op2 = get_irn_n(op2, 1);
366 return new_rd_arm_Mla(env->dbg, env->irg, env->block, op1, op2, op3, env->mode);
369 /* is the first a shifter */
370 v = is_shifter_operand(op1, &mod);
372 op1 = get_irn_n(op1, 0);
373 return new_rd_arm_Add(env->dbg, env->irg, env->block, op2, op1, env->mode,
374 mod, new_tarval_from_long(v, mode_Iu));
376 /* is the second a shifter */
377 v = is_shifter_operand(op2, &mod);
379 op2 = get_irn_n(op2, 0);
380 return new_rd_arm_Add(env->dbg, env->irg, env->block, op1, op2, env->mode,
381 mod, new_tarval_from_long(v, mode_Iu));
385 return new_rd_arm_Add(env->dbg, env->irg, env->block, op1, op2, env->mode, ARM_SHF_NONE, NULL);
388 assert(0 && "unknown mode for add");
393 * Creates an arm Mul.
395 * @param env The transformation environment
396 * @return the created arm Mul node
398 static ir_node *gen_Mul(arm_transform_env_t *env) {
399 ir_node *irn = env->irn;
400 ir_node *op1 = get_Mul_left(irn);
401 ir_node *op2 = get_Mul_right(irn);
403 assert(env->mode != mode_E && "IEEE Extended FP not supported");
405 if (mode_is_float(env->mode)) {
406 env->cg->have_fp = 1;
407 return new_rd_arm_fMul(env->dbg, env->irg, env->block, op1, op2, env->mode);
409 return new_rd_arm_Mul(env->dbg, env->irg, env->block, op1, op2, env->mode);
413 * Creates an arm floating point Div.
415 * @param env The transformation environment
416 * @return the created arm fDiv node
418 static ir_node *gen_Quot(arm_transform_env_t *env) {
419 ir_node *irn = env->irn;
420 ir_node *op1 = get_Quot_left(irn);
421 ir_node *op2 = get_Quot_right(irn);
423 assert(mode_is_float(get_irn_mode(op1)));
424 assert(get_irn_mode(op1) != mode_E && "IEEE Extended FP not supported");
426 return new_rd_arm_fDiv(env->dbg, env->irg, env->block, op1, op2, env->mode);
429 #define GEN_INT_OP(op) \
430 static ir_node *gen_ ## op(arm_transform_env_t *env) { \
431 ir_node *irn = env->irn; \
432 ir_node *op1 = get_ ## op ## _left(irn); \
433 ir_node *op2 = get_ ## op ## _right(irn); \
435 arm_shift_modifier mod; \
437 if (is_arm_Mov_i(op1)) \
438 return new_rd_arm_ ## op ## _i(env->dbg, env->irg, env->block, op2, env->mode, \
439 get_arm_value(op1)); \
440 if (is_arm_Mov_i(op2)) \
441 return new_rd_arm_ ## op ## _i(env->dbg, env->irg, env->block, op1, env->mode, \
442 get_arm_value(op2)); \
443 /* is the first a shifter */ \
444 v = is_shifter_operand(op1, &mod); \
446 op1 = get_irn_n(op1, 0); \
447 return new_rd_arm_ ## op(env->dbg, env->irg, env->block, op2, op1, env->mode, \
448 mod, new_tarval_from_long(v, mode_Iu)); \
450 /* is the second a shifter */ \
451 v = is_shifter_operand(op2, &mod); \
453 op2 = get_irn_n(op2, 0); \
454 return new_rd_arm_ ## op(env->dbg, env->irg, env->block, op1, op2, env->mode, \
455 mod, new_tarval_from_long(v, mode_Iu)); \
458 return new_rd_arm_ ## op(env->dbg, env->irg, env->block, op1, op2, env->mode, ARM_SHF_NONE, NULL); \
463 * Creates an arm And.
465 * @param env The transformation environment
466 * @return the created arm And node
468 static ir_node *gen_And(arm_transform_env_t *env);
472 * Creates an arm Orr.
474 * @param env The transformation environment
475 * @return the created arm Or node
477 static ir_node *gen_Or(arm_transform_env_t *env);
481 * Creates an arm Eor.
483 * @param env The transformation environment
484 * @return the created arm Eor node
486 static ir_node *gen_Eor(arm_transform_env_t *env);
490 * Creates an arm Sub.
492 * @param env The transformation environment
493 * @return the created arm Sub node
495 static ir_node *gen_Sub(arm_transform_env_t *env) {
496 ir_node *irn = env->irn;
497 ir_node *op1 = get_Sub_left(irn);
498 ir_node *op2 = get_Sub_right(irn);
500 arm_shift_modifier mod;
502 assert(env->mode != mode_E && "IEEE Extended FP not supported");
504 if (mode_is_float(env->mode)) {
505 env->cg->have_fp = 1;
506 return new_rd_arm_fSub(env->dbg, env->irg, env->block, op1, op2, env->mode);
508 if (mode_is_numP(env->mode)) {
509 if (is_arm_Mov_i(op1))
510 return new_rd_arm_Rsb_i(env->dbg, env->irg, env->block, op2, env->mode,
512 if (is_arm_Mov_i(op2))
513 return new_rd_arm_Sub_i(env->dbg, env->irg, env->block, op1, env->mode,
516 /* is the first a shifter */
517 v = is_shifter_operand(op1, &mod);
519 op1 = get_irn_n(op1, 0);
520 return new_rd_arm_Rsb(env->dbg, env->irg, env->block, op2, op1, env->mode,
521 mod, new_tarval_from_long(v, mode_Iu));
523 /* is the second a shifter */
524 v = is_shifter_operand(op2, &mod);
526 op2 = get_irn_n(op2, 0);
527 return new_rd_arm_Sub(env->dbg, env->irg, env->block, op1, op2, env->mode,
528 mod, new_tarval_from_long(v, mode_Iu));
531 return new_rd_arm_Sub(env->dbg, env->irg, env->block, op1, op2, env->mode, ARM_SHF_NONE, NULL);
533 assert(0 && "unknown mode for sub");
538 * Creates an arm Shl.
540 * @param env The transformation environment
541 * @return the created arm Shl node
543 static ir_node *gen_Shl(arm_transform_env_t *env) {
545 ir_node *irn = env->irn;
546 ir_node *op1 = get_Shl_left(irn);
547 ir_node *op2 = get_Shl_right(irn);
549 if (is_arm_Mov_i(op2)) {
550 result = new_rd_arm_Mov(env->dbg, env->irg, env->block, op1, env->mode,
551 ARM_SHF_LSL, get_arm_value(op2));
553 result = new_rd_arm_Shl(env->dbg, env->irg, env->block, op1, op2, env->mode);
559 * Creates an arm Shr.
561 * @param env The transformation environment
562 * @return the created arm Shr node
564 static ir_node *gen_Shr(arm_transform_env_t *env) {
566 ir_node *irn = env->irn;
567 ir_node *op1 = get_Shr_left(irn);
568 ir_node *op2 = get_Shr_right(irn);
570 if (is_arm_Mov_i(op2)) {
571 result = new_rd_arm_Mov(env->dbg, env->irg, env->block, op1, env->mode,
572 ARM_SHF_LSR, get_arm_value(op2));
574 result = new_rd_arm_Shr(env->dbg, env->irg, env->block, op1, op2, env->mode);
580 * Creates an arm Shrs.
582 * @param env The transformation environment
583 * @return the created arm Shrs node
585 static ir_node *gen_Shrs(arm_transform_env_t *env) {
587 ir_node *irn = env->irn;
588 ir_node *op1 = get_Shrs_left(irn);
589 ir_node *op2 = get_Shrs_right(irn);
591 if (is_arm_Mov_i(op2)) {
592 result = new_rd_arm_Mov(env->dbg, env->irg, env->block, op1, env->mode,
593 ARM_SHF_ASR, get_arm_value(op2));
595 result = new_rd_arm_Shrs(env->dbg, env->irg, env->block, op1, op2, env->mode);
601 * Transforms a Not node.
603 * @param env The transformation environment
604 * @return the created arm Not node
606 static ir_node *gen_Not(arm_transform_env_t *env) {
607 ir_node *op = get_Not_op(env->irn);
609 arm_shift_modifier mod = ARM_SHF_NONE;
612 v = is_shifter_operand(op, &mod);
614 op = get_irn_n(op, 0);
615 tv = new_tarval_from_long(v, mode_Iu);
617 return new_rd_arm_Mvn(env->dbg, env->irg, env->block, op, env->mode, mod, tv);
621 * Transforms an Abs node.
623 * @param env The transformation environment
624 * @return the created arm Abs node
626 static ir_node *gen_Abs(arm_transform_env_t *env) {
627 ir_node *op = get_Abs_op(env->irn);
629 assert(env->mode != mode_E && "IEEE Extended FP not supported");
631 if (mode_is_float(env->mode)) {
632 env->cg->have_fp = 1;
633 return new_rd_arm_fAbs(env->dbg, env->irg, env->block, op, env->mode);
636 return new_rd_arm_Abs(env->dbg, env->irg, env->block, op, env->mode);
640 * Transforms a Minus node.
642 * @param env The transformation environment
643 * @return the created arm Minus node
645 static ir_node *gen_Minus(arm_transform_env_t *env) {
646 ir_node *op = get_Minus_op(env->irn);
648 if (mode_is_float(env->mode)) {
649 return new_rd_arm_fMinus(env->dbg, env->irg, env->block, op, env->mode);
651 return new_rd_arm_Rsb_i(env->dbg, env->irg, env->block, op, env->mode, get_mode_null(env->mode));
657 * @param mod the debug module
658 * @param block the block the new node should belong to
659 * @param node the ir Load node
660 * @param mode node mode
661 * @return the created arm Load node
663 static ir_node *gen_Load(arm_transform_env_t *env) {
664 ir_node *node = env->irn;
665 ir_mode *mode = get_Load_mode(node);
667 if (mode_is_float(mode)) {
668 env->cg->have_fp = 1;
669 /* FIXME: set the load mode */
670 return new_rd_arm_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
672 if (mode == mode_Bu) {
673 return new_rd_arm_Loadb(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
675 if (mode == mode_Bs) {
676 return new_rd_arm_Loadbs(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
678 if (mode == mode_Hu) {
679 return new_rd_arm_Loadh(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
681 if (mode == mode_Hs) {
682 return new_rd_arm_Loadhs(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
684 if (mode_is_reference(mode)) {
685 return new_rd_arm_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
687 return new_rd_arm_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
691 * Transforms a Store.
693 * @param mod the debug module
694 * @param block the block the new node should belong to
695 * @param node the ir Store node
696 * @param mode node mode
697 * @return the created arm Store node
699 static ir_node *gen_Store(arm_transform_env_t *env) {
700 ir_node *node = env->irn;
701 ir_mode *mode = get_irn_mode(get_Store_value(node));
702 assert(env->mode != mode_E && "IEEE Extended FP not supported");
704 if (mode_is_float(mode)) {
705 env->cg->have_fp = 1;
706 /* FIXME: set the store mode */
707 return new_rd_arm_fStore(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
709 if (mode == mode_Bu) {
710 return new_rd_arm_Storeb(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
712 if (mode == mode_Bs) {
713 return new_rd_arm_Storebs(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
715 if (mode == mode_Hu) {
716 return new_rd_arm_Storeh(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
718 if (mode == mode_Hs) {
719 return new_rd_arm_Storehs(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
721 return new_rd_arm_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
725 static ir_node *gen_Cond(arm_transform_env_t *env) {
726 ir_node *result = NULL;
727 ir_node *selector = get_Cond_selector(env->irn);
728 ir_node *irn = env->irn;
730 if ( get_irn_mode(selector) == mode_b ) {
732 ir_node *proj_node = get_Cond_selector(irn);
733 ir_node *cmp_node = get_Proj_pred(proj_node);
734 ir_node *op1 = get_Cmp_left(cmp_node);
735 ir_node *op2 = get_Cmp_right(cmp_node);
736 result = new_rd_arm_CondJmp(env->dbg, env->irg, env->block, op1, op2, mode_T);
737 set_arm_proj_num(result, get_Proj_proj(proj_node));
740 ir_node *op = get_irn_n(env->irn, 0);
741 ir_node *const_graph;
746 const ir_edge_t *edge;
753 arm_transform_env_t const_env;
757 foreach_out_edge(irn, edge) {
758 proj = get_edge_src_irn(edge);
759 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
761 pn = get_Proj_proj(proj);
763 min = pn<min ? pn : min;
764 max = pn>max ? pn : max;
767 norm_max = max - translation;
768 norm_min = min - translation;
770 n_projs = norm_max + 1;
771 projs = xcalloc(n_projs , sizeof(ir_node*));
774 foreach_out_edge(irn, edge) {
775 proj = get_edge_src_irn(edge);
776 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
778 pn = get_Proj_proj(proj) - translation;
779 set_Proj_proj(proj, pn);
783 const_node = new_rd_Const(env->dbg, env->irg, env->block, mode_Iu, new_tarval_from_long(translation, mode_Iu));
785 const_env.mode = mode_Is;
786 const_env.irn = const_node;
787 const_graph = gen_Const(&const_env);
788 sub = new_rd_arm_Sub(env->dbg, env->irg, env->block, op, const_graph, get_irn_mode(op), ARM_SHF_NONE, NULL);
789 result = new_rd_arm_SwitchJmp(env->dbg, env->irg, env->block, sub, mode_T);
790 set_arm_n_projs(result, n_projs);
791 set_arm_default_proj_num(result, get_Cond_defaultProj(irn)-translation);
797 * Returns the name of a SymConst.
798 * @param symc the SymConst
799 * @return name of the SymConst
801 const char *get_sc_name(ir_node *symc) {
802 if (get_irn_opcode(symc) != iro_SymConst)
805 switch (get_SymConst_kind(symc)) {
806 case symconst_addr_name:
807 return get_id_str(get_SymConst_name(symc));
809 case symconst_addr_ent:
810 return get_entity_ld_name(get_SymConst_entity(symc));
813 assert(0 && "Unsupported SymConst");
819 static ir_node *gen_SymConst(arm_transform_env_t *env) {
820 return new_rd_arm_SymConst(env->dbg, env->irg, env->block,
821 env->mode, get_sc_name(env->irn));
827 * Transforms a CopyB node.
829 * @param env The transformation environment
830 * @return The transformed node.
832 static ir_node *gen_CopyB(arm_transform_env_t *env) {
834 dbg_info *dbg = env->dbg;
835 ir_graph *irg = env->irg;
836 ir_mode *mode = env->mode;
837 ir_node *block = env->block;
838 ir_node *node = env->irn;
839 ir_node *src = get_CopyB_src(node);
840 ir_node *dst = get_CopyB_dst(node);
841 ir_node *mem = get_CopyB_mem(node);
842 int size = get_type_size_bytes(get_CopyB_type(node));
846 arm_transform_env_t const_env;
847 const_env.block = block;
850 const_env.irn = node;
851 DEBUG_ONLY(const_env.mod = env->mod;)
852 const_env.mode = mode_Iu;
854 src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, src);
855 dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, dst);
857 res = new_rd_arm_CopyB( dbg, irg, block, dst_copy, src_copy, new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), mem, mode);
858 set_arm_value(res, new_tarval_from_long(size, mode_Iu));
867 /********************************************
870 * | |__ ___ _ __ ___ __| | ___ ___
871 * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
872 * | |_) | __/ | | | (_) | (_| | __/\__ \
873 * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
875 ********************************************/
878 * Return an expanding stack offset.
879 * Note that function is called in the transform phase
880 * where the stack offsets are still relative regarding
881 * the first (frame allocating) IncSP.
882 * However this is exactly what we want because frame
883 * access must be done relative the the fist IncSP ...
885 static int get_sp_expand_offset(ir_node *inc_sp) {
886 unsigned offset = be_get_IncSP_offset(inc_sp);
887 be_stack_dir_t dir = be_get_IncSP_direction(inc_sp);
889 if (offset == BE_STACK_FRAME_SIZE)
891 return dir == be_stack_dir_expand ? (int)offset : -(int)offset;
894 static ir_node *gen_StackParam(arm_transform_env_t *env) {
896 ir_node *new_op = NULL;
897 ir_node *node = env->irn;
898 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
899 ir_node *mem = new_rd_NoMem(env->irg);
900 ir_node *ptr = get_irn_n(node, 0);
901 entity *ent = be_get_frame_entity(node);
902 ir_mode *mode = env->mode;
904 // /* If the StackParam has only one user -> */
905 // /* put it in the Block where the user resides */
906 // if (get_irn_n_edges(node) == 1) {
907 // env->block = get_nodes_block(get_edge_src_irn(get_irn_out_edge_first(node)));
910 if (mode_is_float(mode)) {
911 if (USE_SSE2(env->cg))
912 new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
914 env->cg->used_x87 = 1;
915 new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
919 new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
922 set_ia32_frame_ent(new_op, ent);
923 set_ia32_use_frame(new_op);
925 set_ia32_am_support(new_op, ia32_am_Source);
926 set_ia32_op_type(new_op, ia32_AddrModeS);
927 set_ia32_am_flavour(new_op, ia32_B);
928 set_ia32_ls_mode(new_op, mode);
930 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
932 return new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode, 0);
937 * Transforms a FrameAddr into an ia32 Add.
939 static ir_node *gen_be_FrameAddr(arm_transform_env_t *env) {
940 ir_node *node = env->irn;
941 entity *ent = be_get_frame_entity(node);
942 int offset = get_entity_offset_bytes(ent);
943 ir_node *op = get_irn_n(node, 0);
946 if (be_is_IncSP(op)) {
947 /* BEWARE: we get an offset which is absolute from an offset that
948 is relative. Both must be merged */
949 offset += get_sp_expand_offset(op);
951 cnst = create_const_graph_value(env, (unsigned)offset);
952 if (is_arm_Mov_i(cnst)) {
953 return new_rd_arm_Add_i(env->dbg, env->irg, env->block, op, env->mode,
954 get_arm_value(cnst));
956 return new_rd_arm_Add(env->dbg, env->irg, env->block, op, cnst, env->mode, ARM_SHF_NONE, NULL);
960 * Transforms a FrameLoad into an ia32 Load.
962 static ir_node *gen_FrameLoad(arm_transform_env_t *env) {
964 ir_node *new_op = NULL;
965 ir_node *node = env->irn;
966 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
967 ir_node *mem = get_irn_n(node, 0);
968 ir_node *ptr = get_irn_n(node, 1);
969 entity *ent = be_get_frame_entity(node);
970 ir_mode *mode = get_type_mode(get_entity_type(ent));
972 if (mode_is_float(mode)) {
973 if (USE_SSE2(env->cg))
974 new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
976 env->cg->used_x87 = 1;
977 new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
981 new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
984 set_ia32_frame_ent(new_op, ent);
985 set_ia32_use_frame(new_op);
987 set_ia32_am_support(new_op, ia32_am_Source);
988 set_ia32_op_type(new_op, ia32_AddrModeS);
989 set_ia32_am_flavour(new_op, ia32_B);
990 set_ia32_ls_mode(new_op, mode);
992 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1000 * Transforms a FrameStore into an ia32 Store.
1002 static ir_node *gen_FrameStore(arm_transform_env_t *env) {
1004 ir_node *new_op = NULL;
1005 ir_node *node = env->irn;
1006 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1007 ir_node *mem = get_irn_n(node, 0);
1008 ir_node *ptr = get_irn_n(node, 1);
1009 ir_node *val = get_irn_n(node, 2);
1010 entity *ent = be_get_frame_entity(node);
1011 ir_mode *mode = get_irn_mode(val);
1013 if (mode_is_float(mode)) {
1014 if (USE_SSE2(env->cg))
1015 new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1017 env->cg->used_x87 = 1;
1018 new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1021 else if (get_mode_size_bits(mode) == 8) {
1022 new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1025 new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
1028 set_ia32_frame_ent(new_op, ent);
1029 set_ia32_use_frame(new_op);
1031 set_ia32_am_support(new_op, ia32_am_Dest);
1032 set_ia32_op_type(new_op, ia32_AddrModeD);
1033 set_ia32_am_flavour(new_op, ia32_B);
1034 set_ia32_ls_mode(new_op, mode);
1036 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1043 // static ir_node *gen_be_Copy(arm_transform_env_t *env, ir_node *op) {
1044 // return new_rd_arm_Copy(env->dbg, env->irg, env->block, op, env->mode);
1047 /*********************************************************
1050 * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
1051 * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
1052 * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
1053 * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
1055 *********************************************************/
1057 /************************************************************************/
1058 /* move constants out of startblock */
1059 /************************************************************************/
1060 void arm_move_consts(ir_node *node, void *env) {
1061 arm_code_gen_t *cgenv = (arm_code_gen_t *)env;
1062 arm_transform_env_t tenv;
1068 tenv.irg = current_ir_graph;
1069 DEBUG_ONLY(tenv.mod = cgenv->mod);
1072 for (i = 0; i < get_irn_arity(node); i++) {
1073 ir_node *pred = get_irn_n(node,i);
1074 opcode pred_code = get_irn_opcode(pred);
1075 if (pred_code == iro_Const) {
1076 ir_node *const_graph;
1077 tenv.block = get_nodes_block(get_irn_n(get_nodes_block(node),i));
1078 tenv.dbg = get_irn_dbg_info(pred);
1080 tenv.mode = get_irn_mode(pred);
1081 const_graph = create_const_graph(&tenv);
1082 set_irn_n(node, i, const_graph);
1083 } else if (pred_code == iro_SymConst) {
1084 const char *str = get_sc_name(pred);
1085 ir_node *symconst_node;
1086 symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1087 current_ir_graph, get_nodes_block(get_irn_n(get_nodes_block(node),i)),
1088 get_irn_mode(pred), str);
1089 set_irn_n(node, i, symconst_node);
1094 for (i = 0; i < get_irn_arity(node); i++) {
1095 ir_node *pred = get_irn_n(node,i);
1096 opcode pred_code = get_irn_opcode(pred);
1097 if (pred_code == iro_Const) {
1098 ir_node *const_graph;
1099 tenv.block = get_nodes_block(node);
1100 tenv.dbg = get_irn_dbg_info(pred);
1102 tenv.mode = get_irn_mode(pred);
1103 const_graph = create_const_graph(&tenv);
1104 set_irn_n(node, i, const_graph);
1105 } else if (pred_code == iro_SymConst) {
1106 const char *str = get_sc_name(pred);
1107 ir_node *symconst_node;
1108 symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1109 current_ir_graph, get_nodes_block(node),
1110 get_irn_mode(pred), str);
1111 set_irn_n(node, i, symconst_node);
1117 /************************************************************************/
1118 /* move symbolic constants out of startblock */
1119 /************************************************************************/
1120 void arm_move_symconsts(ir_node *node, void *env) {
1126 for (i = 0; i < get_irn_arity(node); i++) {
1127 ir_node *pred = get_irn_n(node,i);
1128 opcode pred_code = get_irn_opcode(pred);
1130 if (pred_code == iro_SymConst) {
1131 const char *str = get_sc_name(pred);
1132 ir_node *symconst_node;
1134 symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
1135 current_ir_graph, get_nodes_block(node), get_irn_mode(pred), str);
1136 set_irn_n(node, i, symconst_node);
1142 * the BAD transformer.
1144 static ir_node *bad_transform(arm_transform_env_t *env) {
1145 ir_fprintf(stderr, "Not implemented: %+F\n", env->irn);
1151 * Enters all transform functions into the generic pointer
1153 void arm_register_transformers(void) {
1154 ir_op *op_Max, *op_Min, *op_Mulh;
1156 /* first clear the generic function pointer for all ops */
1157 clear_irp_opcodes_generic_func();
1159 #define FIRM_OP(a) op_##a->ops.generic = (op_func)gen_##a
1160 #define BAD(a) op_##a->ops.generic = (op_func)bad_transform
1163 FIRM_OP(Add); // done
1164 FIRM_OP(Mul); // done
1165 FIRM_OP(Quot); // done
1166 FIRM_OP(And); // done
1167 FIRM_OP(Or); // done
1168 FIRM_OP(Eor); // done
1170 FIRM_OP(Sub); // done
1171 FIRM_OP(Shl); // done
1172 FIRM_OP(Shr); // done
1173 FIRM_OP(Shrs); // done
1175 FIRM_OP(Minus); // done
1176 FIRM_OP(Not); // done
1177 FIRM_OP(Abs); // done
1179 FIRM_OP(CopyB); // done
1180 FIRM_OP(Const); // TODO: floating point consts
1181 FIRM_OP(Conv); // TODO: floating point conversions
1183 FIRM_OP(Load); // done
1184 FIRM_OP(Store); // done
1187 FIRM_OP(Cond); // integer done
1189 /* TODO: implement these nodes */
1191 IGN(Div); // intrinsic lowering
1192 IGN(Mod); // intrinsic lowering
1193 IGN(DivMod); // TODO: implement DivMod
1197 IGN(Cmp); // done, implemented in cond
1199 /* You probably don't need to handle the following nodes */
1211 IGN(Jmp); // emitter done
1229 FIRM_OP(be_FrameAddr);
1231 op_Max = get_op_Max();
1234 op_Min = get_op_Min();
1237 op_Mulh = get_op_Mulh();
1246 typedef ir_node *(transform_func)(arm_transform_env_t *env);
1249 * Transforms the given firm node (and maybe some other related nodes)
1250 * into one or more assembler nodes.
1252 * @param node the firm node
1253 * @param env the debug module
1255 void arm_transform_node(ir_node *node, void *env) {
1256 arm_code_gen_t *cg = (arm_code_gen_t *)env;
1257 ir_op *op = get_irn_op(node);
1258 ir_node *asm_node = NULL;
1263 DBG((cg->mod, LEVEL_1, "check %+F ... ", node));
1265 if (op->ops.generic) {
1266 arm_transform_env_t tenv;
1267 transform_func *transform = (transform_func *)op->ops.generic;
1270 tenv.block = get_nodes_block(node);
1271 tenv.dbg = get_irn_dbg_info(node);
1272 tenv.irg = current_ir_graph;
1274 tenv.mode = get_irn_mode(node);
1275 DEBUG_ONLY(tenv.mod = cg->mod);
1277 asm_node = (*transform)(&tenv);
1281 exchange(node, asm_node);
1282 DB((cg->mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1285 DB((cg->mod, LEVEL_1, "ignored\n"));