- * @return The created ia32 Sub node
- */
-static ir_node *gen_Sub(ir_node *node) {
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *op1 = get_Sub_left(node);
- ir_node *new_op1 = be_transform_node(op1);
- ir_node *op2 = get_Sub_right(node);
- ir_node *new_op2 = be_transform_node(op2);
- ir_node *new_op = NULL;
- ir_graph *irg = current_ir_graph;
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_mode *mode = get_irn_mode(node);
- ir_node *noreg = ia32_new_NoReg_gp(env_cg);
- ir_node *nomem = new_NoMem();
- ir_node *expr_op, *imm_op;
-
- /* Check if immediate optimization is on and */
- /* if it's an operation with immediate. */
- imm_op = (env_cg->opt & IA32_OPT_IMMOPS) ? get_immediate_op(NULL, new_op2) : NULL;
- expr_op = get_expr_op(new_op1, new_op2);
-
- assert((expr_op || imm_op) && "invalid operands");
-
- if (mode_is_float(mode)) {
- FP_USED(env_cg);
- if (USE_SSE2(env_cg))
- return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xSub);
- else
- return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfsub);
- }
-
- /* integer SUB */
- if (! expr_op) {
- ia32_immop_type_t tp1 = get_ia32_immop_type(new_op1);
- ia32_immop_type_t tp2 = get_ia32_immop_type(new_op2);
-
- /* No expr_op means, that we have two const - one symconst and */
- /* one tarval or another symconst - because this case is not */
- /* covered by constant folding */
- /* We need to check for: */
- /* 1) symconst - const -> becomes a LEA */
- /* 2) symconst - symconst -> becomes a const - LEA as the elf */
- /* linker doesn't support two symconsts */
- if (tp1 == ia32_ImmSymConst && tp2 == ia32_ImmSymConst) {
- /* this is the 2nd case */
- new_op = new_rd_ia32_Lea(dbgi, irg, block, new_op1, noreg);
- set_ia32_am_sc(new_op, get_ia32_Immop_symconst(op2));
- set_ia32_am_sc_sign(new_op);
- set_ia32_am_flavour(new_op, ia32_am_B);
-
- DBG_OPT_LEA3(op1, op2, node, new_op);
- } else if (tp1 == ia32_ImmSymConst) {
- tarval *tv = get_ia32_Immop_tarval(new_op2);
- long offs = get_tarval_long(tv);
-
- new_op = new_rd_ia32_Lea(dbgi, irg, block, noreg, noreg);
- add_irn_dep(new_op, get_irg_frame(irg));
- DBG_OPT_LEA3(op1, op2, node, new_op);
-
- set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op1));
- add_ia32_am_offs_int(new_op, -offs);
- set_ia32_am_flavour(new_op, ia32_am_OB);
- set_ia32_op_type(new_op, ia32_AddrModeS);
- } else if (tp2 == ia32_ImmSymConst) {
- tarval *tv = get_ia32_Immop_tarval(new_op1);
- long offs = get_tarval_long(tv);
-
- new_op = new_rd_ia32_Lea(dbgi, irg, block, noreg, noreg);
- add_irn_dep(new_op, get_irg_frame(irg));
- DBG_OPT_LEA3(op1, op2, node, new_op);
-
- add_ia32_am_offs_int(new_op, offs);
- set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op2));
- set_ia32_am_sc_sign(new_op);
- set_ia32_am_flavour(new_op, ia32_am_OB);
- set_ia32_op_type(new_op, ia32_AddrModeS);
- } else {
- tarval *tv1 = get_ia32_Immop_tarval(new_op1);
- tarval *tv2 = get_ia32_Immop_tarval(new_op2);
- tarval *restv = tarval_sub(tv1, tv2);
-
- DEBUG_ONLY(ir_fprintf(stderr, "Warning: sub with 2 consts not folded: %+F\n", node));
-
- new_op = new_rd_ia32_Const(dbgi, irg, block);
- set_ia32_Const_tarval(new_op, restv);
- DBG_OPT_LEA3(new_op1, new_op2, node, new_op);
- }
-
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
- return new_op;
- } else if (imm_op) {
- if ((env_cg->opt & IA32_OPT_INCDEC) && get_ia32_immop_type(imm_op) == ia32_ImmConst) {
- tarval_classification_t class_tv, class_negtv;
- tarval *tv = get_ia32_Immop_tarval(imm_op);
-
- /* optimize tarvals */
- class_tv = classify_tarval(tv);
- class_negtv = classify_tarval(tarval_neg(tv));
-
- if (class_tv == TV_CLASSIFY_ONE) {
- DB((dbg, LEVEL_2, "Sub(1) to Dec ... "));
- new_op = new_rd_ia32_Dec(dbgi, irg, block, noreg, noreg, expr_op, nomem);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
- return new_op;
- } else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) {
- DB((dbg, LEVEL_2, "Sub(-1) to Inc ... "));
- new_op = new_rd_ia32_Inc(dbgi, irg, block, noreg, noreg, expr_op, nomem);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
- return new_op;
- }
- }
- }
-
- /* This is a normal sub */
- new_op = new_rd_ia32_Sub(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
-
- /* set AM support */
- set_ia32_am_support(new_op, ia32_am_Full, ia32_am_binary);
-
- fold_immediate(new_op, 2, 3);
-
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
-
- return new_op;
-}
-
-
-
-/**
- * Generates an ia32 DivMod with additional infrastructure for the
- * register allocator if needed.
- *
- * @param dividend -no comment- :)
- * @param divisor -no comment- :)
- * @param dm_flav flavour_Div/Mod/DivMod
- * @return The created ia32 DivMod node