+/**
+ * Generate a vfist or vfisttp instruction.
+ */
+static ir_node *gen_vfist(dbg_info *dbgi, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index,
+ ir_node *mem, ir_node *val, ir_node **fist)
+{
+ ir_node *new_node;
+
+ if (ia32_cg_config.use_fisttp) {
+ /* Note: fisttp ALWAYS pop the tos. We have to ensure here that the value is copied
+ if other users exists */
+ const arch_register_class_t *reg_class = &ia32_reg_classes[CLASS_ia32_vfp];
+ ir_node *vfisttp = new_rd_ia32_vfisttp(dbgi, irg, block, base, index, mem, val);
+ ir_node *value = new_r_Proj(irg, block, vfisttp, mode_E, pn_ia32_vfisttp_res);
+ be_new_Keep(reg_class, irg, block, 1, &value);
+
+ new_node = new_r_Proj(irg, block, vfisttp, mode_M, pn_ia32_vfisttp_M);
+ *fist = vfisttp;
+ } else {
+ ir_node *trunc_mode = ia32_new_Fpu_truncate(env_cg);
+
+ /* do a fist */
+ new_node = new_rd_ia32_vfist(dbgi, irg, block, base, index, mem, val, trunc_mode);
+ *fist = new_node;
+ }
+ return new_node;
+}
+/**
+ * Transforms a normal Store.
+ *
+ * @return the created ia32 Store node
+ */
+static ir_node *gen_normal_Store(ir_node *node)
+{
+ ir_node *val = get_Store_value(node);
+ ir_mode *mode = get_irn_mode(val);
+ ir_node *block = get_nodes_block(node);
+ ir_node *new_block = be_transform_node(block);
+ ir_node *ptr = get_Store_ptr(node);
+ ir_node *mem = get_Store_mem(node);
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *noreg = ia32_new_NoReg_gp(env_cg);
+ ir_node *new_val, *new_node, *store;
+ ia32_address_t addr;
+
+ /* check for destination address mode */
+ new_node = try_create_dest_am(node);
+ if (new_node != NULL)
+ return new_node;
+
+ /* construct store address */
+ memset(&addr, 0, sizeof(addr));
+ ia32_create_address_mode(&addr, ptr, /*force=*/0);
+
+ if (addr.base == NULL) {
+ addr.base = noreg;
+ } else {
+ addr.base = be_transform_node(addr.base);
+ }
+
+ if (addr.index == NULL) {
+ addr.index = noreg;
+ } else {
+ addr.index = be_transform_node(addr.index);
+ }
+ addr.mem = be_transform_node(mem);
+
+ if (mode_is_float(mode)) {
+ /* Convs (and strict-Convs) before stores are unnecessary if the mode
+ is the same. */
+ while (is_Conv(val) && mode == get_irn_mode(val)) {
+ ir_node *op = get_Conv_op(val);
+ if (!mode_is_float(get_irn_mode(op)))
+ break;
+ val = op;
+ }
+ new_val = be_transform_node(val);
+ if (ia32_cg_config.use_sse2) {
+ new_node = new_rd_ia32_xStore(dbgi, irg, new_block, addr.base,
+ addr.index, addr.mem, new_val);
+ } else {
+ new_node = new_rd_ia32_vfst(dbgi, irg, new_block, addr.base,
+ addr.index, addr.mem, new_val, mode);
+ }
+ store = new_node;
+ } else if (!ia32_cg_config.use_sse2 && is_float_to_int32_conv(val)) {
+ val = get_Conv_op(val);
+
+ /* We can skip ALL Convs (and strict-Convs) before stores. */
+ while (is_Conv(val)) {
+ val = get_Conv_op(val);
+ }
+ new_val = be_transform_node(val);
+ new_node = gen_vfist(dbgi, irg, new_block, addr.base, addr.index, addr.mem, new_val, &store);
+ } else {
+ new_val = create_immediate_or_transform(val, 0);
+ assert(mode != mode_b);
+
+ if (get_mode_size_bits(mode) == 8) {
+ new_node = new_rd_ia32_Store8Bit(dbgi, irg, new_block, addr.base,
+ addr.index, addr.mem, new_val);
+ } else {
+ new_node = new_rd_ia32_Store(dbgi, irg, new_block, addr.base,
+ addr.index, addr.mem, new_val);
+ }
+ store = new_node;
+ }
+
+ set_irn_pinned(store, get_irn_pinned(node));
+ set_ia32_op_type(store, ia32_AddrModeD);
+ set_ia32_ls_mode(store, mode);
+
+ set_address(store, &addr);
+ SET_IA32_ORIG_NODE(store, ia32_get_old_node_name(env_cg, node));
+
+ return new_node;
+}
+
+/**
+ * Transforms a Store.
+ *
+ * @return the created ia32 Store node
+ */
+static ir_node *gen_Store(ir_node *node)
+{
+ ir_node *val = get_Store_value(node);
+ ir_mode *mode = get_irn_mode(val);
+
+ if (mode_is_float(mode) && is_Const(val)) {
+ int transform = 1;
+
+ /* we are storing a floating point constant */
+ if (ia32_cg_config.use_sse2) {
+ transform = !is_simple_sse_Const(val);
+ } else {
+ transform = !is_simple_x87_Const(val);
+ }
+ if (transform)
+ return gen_float_const_Store(node, val);
+ }
+ return gen_normal_Store(node);
+}
+
+/**
+ * Transforms a Switch.
+ *
+ * @return the created ia32 SwitchJmp node
+ */
+static ir_node *create_Switch(ir_node *node)
+{
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *block = be_transform_node(get_nodes_block(node));
+ ir_node *sel = get_Cond_selector(node);
+ ir_node *new_sel = be_transform_node(sel);
+ int switch_min = INT_MAX;
+ int switch_max = INT_MIN;
+ long default_pn = get_Cond_defaultProj(node);
+ ir_node *new_node;
+ const ir_edge_t *edge;
+
+ assert(get_mode_size_bits(get_irn_mode(sel)) == 32);
+
+ /* determine the smallest switch case value */
+ foreach_out_edge(node, edge) {
+ ir_node *proj = get_edge_src_irn(edge);
+ long pn = get_Proj_proj(proj);
+ if(pn == default_pn)
+ continue;
+
+ if(pn < switch_min)
+ switch_min = pn;
+ if(pn > switch_max)
+ switch_max = pn;
+ }
+
+ if((unsigned) (switch_max - switch_min) > 256000) {
+ panic("Size of switch %+F bigger than 256000", node);
+ }
+
+ if (switch_min != 0) {
+ ir_node *noreg = ia32_new_NoReg_gp(env_cg);
+
+ /* if smallest switch case is not 0 we need an additional sub */