+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, node));
+
+ return new_op;
+}
+
+/**
+ * In case SSE is used we need to copy the result from XMM0 to FPU TOS before return.
+ */
+static ir_node *gen_be_Return(ia32_transform_env_t *env, ir_node *node) {
+ ir_graph *irg = env->irg;
+ ir_node *ret_val = get_irn_n(node, be_pos_Return_val);
+ ir_node *ret_mem = get_irn_n(node, be_pos_Return_mem);
+ ir_entity *ent = get_irg_entity(irg);
+ ir_type *tp = get_entity_type(ent);
+ dbg_info *dbgi;
+ ir_node *block;
+ ir_type *res_type;
+ ir_mode *mode;
+ ir_node *frame, *sse_store, *fld, *mproj, *barrier;
+ ir_node *new_barrier, *new_ret_val, *new_ret_mem;
+ ir_node **in;
+ int pn_ret_val, pn_ret_mem, arity, i;
+
+ assert(ret_val != NULL);
+ if (be_Return_get_n_rets(node) < 1 || ! USE_SSE2(env->cg)) {
+ return duplicate_node(env, node);
+ }
+
+ res_type = get_method_res_type(tp, 0);
+
+ if (! is_Primitive_type(res_type)) {
+ return duplicate_node(env, node);
+ }
+
+ mode = get_type_mode(res_type);
+ if (! mode_is_float(mode)) {
+ return duplicate_node(env, node);
+ }
+
+ assert(get_method_n_ress(tp) == 1);
+
+ pn_ret_val = get_Proj_proj(ret_val);
+ pn_ret_mem = get_Proj_proj(ret_mem);
+
+ /* get the Barrier */
+ barrier = get_Proj_pred(ret_val);
+
+ /* get result input of the Barrier */
+ ret_val = get_irn_n(barrier, pn_ret_val);
+ new_ret_val = transform_node(env, ret_val);
+
+ /* get memory input of the Barrier */
+ ret_mem = get_irn_n(barrier, pn_ret_mem);
+ new_ret_mem = transform_node(env, ret_mem);
+
+ frame = get_irg_frame(irg);
+
+ dbgi = get_irn_dbg_info(barrier);
+ block = transform_node(env, get_nodes_block(barrier));
+
+ /* store xmm0 onto stack */
+ sse_store = new_rd_ia32_xStoreSimple(dbgi, irg, block, frame, new_ret_val, new_ret_mem);
+ set_ia32_ls_mode(sse_store, mode);
+ set_ia32_op_type(sse_store, ia32_AddrModeD);
+ set_ia32_use_frame(sse_store);
+ set_ia32_am_flavour(sse_store, ia32_am_B);
+ set_ia32_am_support(sse_store, ia32_am_Dest);
+
+ /* load into st0 */
+ fld = new_rd_ia32_SetST0(dbgi, irg, block, frame, sse_store);
+ set_ia32_ls_mode(fld, mode);
+ set_ia32_op_type(fld, ia32_AddrModeS);
+ set_ia32_use_frame(fld);
+ set_ia32_am_flavour(fld, ia32_am_B);
+ set_ia32_am_support(fld, ia32_am_Source);
+
+ mproj = new_r_Proj(irg, block, fld, mode_M, pn_ia32_SetST0_M);
+ fld = new_r_Proj(irg, block, fld, mode_vfp, pn_ia32_SetST0_res);
+ arch_set_irn_register(env->cg->arch_env, fld, &ia32_vfp_regs[REG_VF0]);
+
+ /* create a new barrier */
+ arity = get_irn_arity(barrier);
+ in = alloca(arity * sizeof(in[0]));
+ for (i = 0; i < arity; ++i) {
+ ir_node *new_in;
+
+ if (i == pn_ret_val) {
+ new_in = fld;
+ } else if (i == pn_ret_mem) {
+ new_in = mproj;
+ } else {
+ ir_node *in = get_irn_n(barrier, i);
+ new_in = transform_node(env, in);
+ }
+ in[i] = new_in;
+ }
+
+ new_barrier = new_ir_node(dbgi, irg, block,
+ get_irn_op(barrier), get_irn_mode(barrier),
+ arity, in);
+ copy_node_attr(barrier, new_barrier);
+ duplicate_deps(env, barrier, new_barrier);
+ set_new_node(barrier, new_barrier);
+ mark_irn_visited(barrier);
+
+ /* transform normally */
+ return duplicate_node(env, node);
+}
+
+/**
+ * Transform a be_AddSP into an ia32_AddSP. Eat up const sizes.
+ */
+static ir_node *gen_be_AddSP(ia32_transform_env_t *env, ir_node *node) {
+ ir_node *block = transform_node(env, get_nodes_block(node));
+ ir_node *sz = get_irn_n(node, be_pos_AddSP_size);
+ ir_node *new_sz = transform_node(env, sz);
+ ir_node *sp = get_irn_n(node, be_pos_AddSP_old_sp);
+ ir_node *new_sp = transform_node(env, sp);
+ ir_graph *irg = env->irg;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *noreg = ia32_new_NoReg_gp(env->cg);
+ ir_node *nomem = new_NoMem();
+ ir_node *new_op;
+
+ /* ia32 stack grows in reverse direction, make a SubSP */
+ new_op = new_rd_ia32_SubSP(dbgi, irg, block, noreg, noreg, new_sp, new_sz, nomem);
+ set_ia32_am_support(new_op, ia32_am_Source);
+ fold_immediate(env, new_op, 2, 3);
+
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, node));
+
+ return new_op;
+}
+
+/**
+ * Transform a be_SubSP into an ia32_SubSP. Eat up const sizes.
+ */
+static ir_node *gen_be_SubSP(ia32_transform_env_t *env, ir_node *node) {
+ ir_node *block = transform_node(env, get_nodes_block(node));
+ ir_node *sz = get_irn_n(node, be_pos_SubSP_size);
+ ir_node *new_sz = transform_node(env, sz);
+ ir_node *sp = get_irn_n(node, be_pos_SubSP_old_sp);
+ ir_node *new_sp = transform_node(env, sp);
+ ir_graph *irg = env->irg;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *noreg = ia32_new_NoReg_gp(env->cg);
+ ir_node *nomem = new_NoMem();
+ ir_node *new_op;
+
+ /* ia32 stack grows in reverse direction, make an AddSP */
+ new_op = new_rd_ia32_AddSP(dbgi, irg, block, noreg, noreg, new_sp, new_sz, nomem);
+ set_ia32_am_support(new_op, ia32_am_Source);
+ fold_immediate(env, new_op, 2, 3);
+
+ SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, node));