2008-07-26 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini-ppc.c
index dc0b351f957efc9e45d277bcfc5dfb101c1babe8..f5f84c98004dbbc77af7eab0fa95ba49d3c33751 100644 (file)
@@ -15,7 +15,7 @@
 
 #include "mini-ppc.h"
 #include "inssel.h"
-#include "cpu-g4.h"
+#include "cpu-ppc.h"
 #include "trace.h"
 #ifdef __APPLE__
 #include <sys/sysctl.h>
@@ -316,7 +316,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
 
                g_assert ((code - start) <= 16);
 
-               mono_arch_flush_icache (code, 16);
+               mono_arch_flush_icache (start, 16);
                cached = start;
                mono_mini_arch_unlock ();
                return cached;
@@ -350,7 +350,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
 
                g_assert ((code - start) <= size);
 
-               mono_arch_flush_icache (code, size);
+               mono_arch_flush_icache (start, size);
                cache [sig->param_count] = start;
                mono_mini_arch_unlock ();
                return start;
@@ -359,7 +359,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
 }
 
 gpointer
-mono_arch_get_this_arg_from_call (MonoMethodSignature *sig, gssize *regs, guint8 *code)
+mono_arch_get_this_arg_from_call (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, gssize *regs, guint8 *code)
 {
        /* FIXME: handle returning a struct */
        if (MONO_TYPE_ISSTRUCT (sig->ret))
@@ -558,9 +558,6 @@ mono_arch_flush_icache (guint8 *code, gint size)
        asm ("isync");
 }
 
-#define NOT_IMPLEMENTED(x) \
-                g_error ("FIXME: %s is not yet implemented. (trampoline)", x);
-
 #ifdef __APPLE__
 #define ALWAYS_ON_STACK(s) s
 #define FP_ALSO_IN_REG(s) s
@@ -1105,6 +1102,11 @@ mono_arch_allocate_vars (MonoCompile *m)
 
 }
 
+void
+mono_arch_create_vars (MonoCompile *cfg)
+{
+}
+
 /* Fixme: we need an alignment solution for enter_method and mono_arch_call_opcode,
  * currently alignment in mono_arch_call_opcode is computed without arch_get_argument_info 
  */
@@ -1143,7 +1145,6 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, MonoCallInst *call,
                        MONO_INST_NEW (cfg, arg, OP_OUTARG);
                        arg->inst_imm = cinfo->sig_cookie.offset;
                        arg->inst_left = sig_arg;
-                       
                        /* prepend, so they get reversed */
                        arg->next = call->out_args;
                        call->out_args = arg;
@@ -1159,7 +1160,7 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, MonoCallInst *call,
                        arg->inst_left = in;
                        arg->inst_call = call;
                        arg->type = in->type;
-                       /* prepend, we'll need to reverse them later */
+                       /* prepend, so they get reversed */
                        arg->next = call->out_args;
                        call->out_args = arg;
                        if (ainfo->regtype == RegTypeGeneral) {
@@ -1229,6 +1230,7 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, MonoCallInst *call,
                }
                call->out_args = prev;
        }
+
        call->stack_usage = cinfo->stack_usage;
        cfg->param_area = MAX (cfg->param_area, cinfo->stack_usage);
        cfg->flags |= MONO_CFG_HAS_CALLS;
@@ -1241,6 +1243,172 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, MonoCallInst *call,
        return call;
 }
 
+void
+mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
+{
+       MonoInst *in, *ins;
+       MonoMethodSignature *sig;
+       int i, n;
+       CallInfo *cinfo;
+
+       sig = call->signature;
+       n = sig->param_count + sig->hasthis;
+       
+       cinfo = calculate_sizes (sig, sig->pinvoke);
+
+       for (i = 0; i < n; ++i) {
+               ArgInfo *ainfo = cinfo->args + i;
+               MonoType *t;
+
+               if (i >= sig->hasthis)
+                       t = sig->params [i - sig->hasthis];
+               else
+                       t = &mono_defaults.int_class->byval_arg;
+               t = mono_type_get_underlying_type (t);
+
+               if ((sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) {
+                       /* FIXME: */
+                       NOT_IMPLEMENTED;
+               }
+
+               in = call->args [i];
+
+               if (ainfo->regtype == RegTypeGeneral) {
+                       if (!t->byref && ((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) {
+                               MONO_INST_NEW (cfg, ins, OP_MOVE);
+                               ins->dreg = mono_alloc_ireg (cfg);
+                               ins->sreg1 = in->dreg + 1;
+                               MONO_ADD_INS (cfg->cbb, ins);
+                               mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, FALSE);
+
+                               MONO_INST_NEW (cfg, ins, OP_MOVE);
+                               ins->dreg = mono_alloc_ireg (cfg);
+                               ins->sreg1 = in->dreg + 2;
+                               MONO_ADD_INS (cfg->cbb, ins);
+                               mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg + 1, FALSE);
+                       } else {
+                               MONO_INST_NEW (cfg, ins, OP_MOVE);
+                               ins->dreg = mono_alloc_ireg (cfg);
+                               ins->sreg1 = in->dreg;
+                               MONO_ADD_INS (cfg->cbb, ins);
+
+                               mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, FALSE);
+                       }
+               } else if (ainfo->regtype == RegTypeStructByAddr) {
+                       if (ainfo->offset) {
+                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, ppc_r1, ainfo->offset, in->dreg);
+                       } else {
+                               MONO_INST_NEW (cfg, ins, OP_MOVE);
+                               ins->dreg = mono_alloc_ireg (cfg);
+                               ins->sreg1 = in->dreg;
+                               MONO_ADD_INS (cfg->cbb, ins);
+
+                               mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, FALSE);
+                       }
+               } else if (ainfo->regtype == RegTypeStructByVal) {
+                       /* this is further handled in mono_arch_emit_outarg_vt () */
+                       MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
+                       ins->opcode = OP_OUTARG_VT;
+                       ins->sreg1 = in->dreg;
+                       ins->klass = in->klass;
+                       ins->inst_p0 = call;
+                       ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
+                       memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
+                       MONO_ADD_INS (cfg->cbb, ins);
+               } else if (ainfo->regtype == RegTypeBase) {
+                       if (!t->byref && ((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) {
+                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, ppc_r1, ainfo->offset, in->dreg);
+                       } else if (!t->byref && ((t->type == MONO_TYPE_R4) || (t->type == MONO_TYPE_R8))) {
+                               if (t->type == MONO_TYPE_R8)
+                                       MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, ppc_r1, ainfo->offset, in->dreg);
+                               else
+                                       MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, ppc_r1, ainfo->offset, in->dreg);
+                       } else {
+                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, ppc_r1, ainfo->offset, in->dreg);
+                       }
+               } else if (ainfo->regtype == RegTypeFP) {
+                       MONO_INST_NEW (cfg, ins, OP_FMOVE);
+                       ins->dreg = mono_alloc_freg (cfg);
+                       ins->sreg1 = in->dreg;
+                       MONO_ADD_INS (cfg->cbb, ins);
+
+                       mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, TRUE);
+                       cfg->flags |= MONO_CFG_HAS_FPOUT;
+               } else {
+                       g_assert_not_reached ();
+               }
+       }
+
+       if (cinfo->struct_ret) {
+               MonoInst *vtarg;
+
+               MONO_INST_NEW (cfg, vtarg, OP_MOVE);
+               vtarg->sreg1 = call->vret_var->dreg;
+               vtarg->dreg = mono_alloc_preg (cfg);
+               MONO_ADD_INS (cfg->cbb, vtarg);
+
+               mono_call_inst_add_outarg_reg (cfg, call, vtarg->dreg, cinfo->struct_ret, FALSE);
+       }
+
+       call->stack_usage = cinfo->stack_usage;
+       cfg->param_area = MAX (cfg->param_area, cinfo->stack_usage);
+       cfg->flags |= MONO_CFG_HAS_CALLS;
+
+       g_free (cinfo);
+}
+
+void
+mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
+{
+       MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
+       ArgInfo *ainfo = ins->inst_p1;
+       int ovf_size = ainfo->vtsize;
+       int doffset = ainfo->offset;
+       int i, soffset, dreg;
+
+       /* FIXME: handle darwin's 1/2 byte structs */
+       soffset = 0;
+       for (i = 0; i < ainfo->size; ++i) {
+               dreg = mono_alloc_ireg (cfg);
+               MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, src->dreg, soffset);
+               mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg + i, FALSE);
+               soffset += sizeof (gpointer);
+       }
+       //g_print ("vt size: %d at R%d + %d\n", doffset, vt->inst_basereg, vt->inst_offset);
+       if (ovf_size != 0)
+               mini_emit_memcpy2 (cfg, ppc_r1, doffset, src->dreg, soffset, ovf_size * sizeof (gpointer), 0);
+}
+
+void
+mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
+{
+       MonoType *ret = mono_type_get_underlying_type (mono_method_signature (method)->ret);
+
+       if (!ret->byref) {
+               if (ret->type == MONO_TYPE_I8 || ret->type == MONO_TYPE_U8) {
+                       MonoInst *ins;
+
+                       MONO_INST_NEW (cfg, ins, OP_SETLRET);
+                       ins->sreg1 = val->dreg + 1;
+                       ins->sreg2 = val->dreg + 2;
+                       MONO_ADD_INS (cfg->cbb, ins);
+                       return;
+               }
+               if (ret->type == MONO_TYPE_R8 || ret->type == MONO_TYPE_R4) {
+                       MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
+                       return;
+               }
+       }
+       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
+}
+
+/* FIXME: this is just a useless hint: fix the interface to include the opcode */
+gboolean
+mono_arch_is_inst_imm (gint64 imm)
+{
+       return TRUE;
+}
+
 /*
  * Allow tracing to work with this interface (with an optional argument)
  */
@@ -1442,14 +1610,17 @@ if (ins->flags & MONO_INST_BRLABEL) { \
 
 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) EMIT_COND_SYSTEM_EXCEPTION_FLAGS(branch_b0_table [(cond)], branch_b1_table [(cond)], (exc_name))
 
-static void
-peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
+void
+mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-       MonoInst *ins, *last_ins = NULL;
-       ins = bb->code;
+}
 
-       while (ins) {
+void
+mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
+{
+       MonoInst *ins, *n, *last_ins = NULL;
 
+       MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
                switch (ins->opcode) {
                case OP_MUL_IMM: 
                        /* remove unnecessary multiplication with 1 */
@@ -1457,8 +1628,7 @@ peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
                                if (ins->dreg != ins->sreg1) {
                                        ins->opcode = OP_MOVE;
                                } else {
-                                       last_ins->next = ins->next;                             
-                                       ins = ins->next;                                
+                                       MONO_DELETE_INS (bb, ins);
                                        continue;
                                }
                        } else {
@@ -1480,8 +1650,7 @@ peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
                            ins->inst_basereg == last_ins->inst_destbasereg &&
                            ins->inst_offset == last_ins->inst_offset) {
                                if (ins->dreg == last_ins->sreg1) {
-                                       last_ins->next = ins->next;                             
-                                       ins = ins->next;                                
+                                       MONO_DELETE_INS (bb, ins);
                                        continue;
                                } else {
                                        //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -1504,8 +1673,7 @@ peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
                              ins->inst_offset == last_ins->inst_offset) {
 
                                if (ins->dreg == last_ins->dreg) {
-                                       last_ins->next = ins->next;                             
-                                       ins = ins->next;                                
+                                       MONO_DELETE_INS (bb, ins);
                                        continue;
                                } else {
                                        ins->opcode = OP_MOVE;
@@ -1538,7 +1706,7 @@ peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (last_ins && (last_ins->opcode == OP_STOREI1_MEMBASE_REG) &&
                                        ins->inst_basereg == last_ins->inst_destbasereg &&
                                        ins->inst_offset == last_ins->inst_offset) {
-                               ins->opcode = (ins->opcode == OP_LOADI1_MEMBASE) ? CEE_CONV_I1 : CEE_CONV_U1;
+                               ins->opcode = (ins->opcode == OP_LOADI1_MEMBASE) ? OP_ICONV_TO_I1 : OP_ICONV_TO_U1;
                                ins->sreg1 = last_ins->sreg1;                           
                        }
                        break;
@@ -1547,22 +1715,17 @@ peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (last_ins && (last_ins->opcode == OP_STOREI2_MEMBASE_REG) &&
                                        ins->inst_basereg == last_ins->inst_destbasereg &&
                                        ins->inst_offset == last_ins->inst_offset) {
-                               ins->opcode = (ins->opcode == OP_LOADI2_MEMBASE) ? CEE_CONV_I2 : CEE_CONV_U2;
+                               ins->opcode = (ins->opcode == OP_LOADI2_MEMBASE) ? OP_ICONV_TO_I2 : OP_ICONV_TO_U2;
                                ins->sreg1 = last_ins->sreg1;                           
                        }
                        break;
-               case CEE_CONV_I4:
-               case CEE_CONV_U4:
                case OP_MOVE:
-               case OP_SETREG:
                        ins->opcode = OP_MOVE;
                        /* 
                         * OP_MOVE reg, reg 
                         */
                        if (ins->dreg == ins->sreg1) {
-                               if (last_ins)
-                                       last_ins->next = ins->next;                             
-                               ins = ins->next;
+                               MONO_DELETE_INS (bb, ins);
                                continue;
                        }
                        /* 
@@ -1572,8 +1735,7 @@ peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (last_ins && last_ins->opcode == OP_MOVE &&
                            ins->sreg1 == last_ins->dreg &&
                            ins->dreg == last_ins->sreg1) {
-                               last_ins->next = ins->next;                             
-                               ins = ins->next;                                
+                               MONO_DELETE_INS (bb, ins);
                                continue;
                        }
                        break;
@@ -1584,6 +1746,30 @@ peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
        bb->last_ins = last_ins;
 }
 
+void
+mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
+{
+       switch (ins->opcode) {
+       case OP_ICONV_TO_R4: {
+               /* FIXME: change precision for CEE_CONV_R4 */
+               static const guint64 adjust_val = 0x4330000080000000ULL;
+               int msw_reg = mono_regstate_next_int (cfg->rs);
+               int xored = mono_regstate_next_int (cfg->rs);
+               int adj_reg = mono_regstate_next_float (cfg->rs);
+               int tmp_reg = mono_regstate_next_float (cfg->rs);
+               MONO_EMIT_NEW_ICONST (cfg, msw_reg, 0x43300000);
+               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, ppc_sp, -8, msw_reg);
+               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, xored, ins->sreg1, 0x80000000);
+               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, ppc_sp, -4, xored);
+               MONO_EMIT_NEW_LOAD_R8 (cfg, adj_reg, &adjust_val);
+               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, tmp_reg, ppc_sp, -8);
+               MONO_EMIT_NEW_BIALU (cfg, OP_FSUB, ins->dreg, tmp_reg, adj_reg);
+               ins->opcode = OP_NOP;
+               break;
+       }
+       }
+}
+
 /* 
  * the branch_b0_table should maintain the order of these
  * opcodes.
@@ -1628,23 +1814,10 @@ branch_b1_table [] = {
        PPC_BR_LT 
 };
 
-static void
-insert_after_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *to_insert)
-{
-       if (ins == NULL) {
-               ins = bb->code;
-               bb->code = to_insert;
-               to_insert->next = ins;
-       } else {
-               to_insert->next = ins->next;
-               ins->next = to_insert;
-       }
-}
-
-#define NEW_INS(cfg,dest,op) do {       \
+#define NEW_INS(cfg,dest,op) do {                                      \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
                (dest)->opcode = (op);  \
-               insert_after_ins (bb, last_ins, (dest)); \
+               mono_bblock_insert_after_ins (bb, last_ins, (dest));    \
        } while (0)
 
 static int
@@ -1652,27 +1825,29 @@ map_to_reg_reg_op (int op)
 {
        switch (op) {
        case OP_ADD_IMM:
-               return CEE_ADD;
+               return OP_IADD;
        case OP_SUB_IMM:
-               return CEE_SUB;
+               return OP_ISUB;
        case OP_AND_IMM:
-               return CEE_AND;
+               return OP_IAND;
        case OP_COMPARE_IMM:
                return OP_COMPARE;
+       case OP_ICOMPARE_IMM:
+               return OP_ICOMPARE;
        case OP_ADDCC_IMM:
-               return OP_ADDCC;
+               return OP_IADDCC;
        case OP_ADC_IMM:
-               return OP_ADC;
+               return OP_IADC;
        case OP_SUBCC_IMM:
-               return OP_SUBCC;
+               return OP_ISUBCC;
        case OP_SBB_IMM:
-               return OP_SBB;
+               return OP_ISBB;
        case OP_OR_IMM:
-               return CEE_OR;
+               return OP_IOR;
        case OP_XOR_IMM:
-               return CEE_XOR;
+               return OP_IXOR;
        case OP_MUL_IMM:
-               return CEE_MUL;
+               return OP_IMUL;
        case OP_LOAD_MEMBASE:
                return OP_LOAD_MEMINDEX;
        case OP_LOADI4_MEMBASE:
@@ -1712,19 +1887,23 @@ map_to_reg_reg_op (int op)
        case OP_STOREI4_MEMBASE_IMM:
                return OP_STOREI4_MEMBASE_REG;
        }
-       g_assert_not_reached ();
+       return mono_op_imm_to_op (op);
 }
 
+//#define map_to_reg_reg_op(op) (cfg->new_ir? mono_op_imm_to_op (op): map_to_reg_reg_op (op))
+
 #define compare_opcode_is_unsigned(opcode) \
                (((opcode) >= CEE_BNE_UN && (opcode) <= CEE_BLT_UN) ||  \
+               (((opcode) >= OP_IBNE_UN && (opcode) <= OP_IBLT_UN) ||  \
                ((opcode) >= OP_COND_EXC_NE_UN && (opcode) <= OP_COND_EXC_LT_UN) ||     \
-               ((opcode) == OP_CLT_UN || (opcode) == OP_CGT_UN))
+               ((opcode) >= OP_COND_EXC_INE_UN && (opcode) <= OP_COND_EXC_ILT_UN) ||   \
+               ((opcode) == OP_CLT_UN || (opcode) == OP_CGT_UN || (opcode) == OP_ICLT_UN || (opcode) == OP_ICGT_UN)))
 /*
  * Remove from the instruction list the instructions that can't be
  * represented with very simple instructions with no register
  * requirements.
  */
-static void
+void
 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
        MonoInst *ins, *next, *temp, *last_ins = NULL;
@@ -1734,20 +1913,60 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
        if (bb->max_vreg > cfg->rs->next_vreg)
                cfg->rs->next_vreg = bb->max_vreg;
 
-       ins = bb->code;
-       while (ins) {
+       MONO_BB_FOR_EACH_INS (bb, ins) {
 loop_start:
                switch (ins->opcode) {
+               case OP_IDIV_UN_IMM:
+               case OP_IDIV_IMM:
+               case OP_IREM_IMM:
+               case OP_IREM_UN_IMM:
+                       NEW_INS (cfg, temp, OP_ICONST);
+                       temp->inst_c0 = ins->inst_imm;
+                       temp->dreg = mono_regstate_next_int (cfg->rs);
+                       ins->sreg2 = temp->dreg;
+                       if (ins->opcode == OP_IDIV_IMM)
+                               ins->opcode = OP_IDIV;
+                       else if (ins->opcode == OP_IREM_IMM)
+                               ins->opcode = OP_IREM;
+                       else if (ins->opcode == OP_IDIV_UN_IMM)
+                               ins->opcode = OP_IDIV_UN;
+                       else if (ins->opcode == OP_IREM_UN_IMM)
+                               ins->opcode = OP_IREM_UN;
+                       last_ins = temp;
+                       /* handle rem separately */
+                       goto loop_start;
+               case OP_IREM:
+               case OP_IREM_UN: {
+                       MonoInst *mul;
+                       /* we change a rem dest, src1, src2 to
+                        * div temp1, src1, src2
+                        * mul temp2, temp1, src2
+                        * sub dest, src1, temp2
+                        */
+                       NEW_INS (cfg, mul, OP_IMUL);
+                       NEW_INS (cfg, temp, ins->opcode == OP_IREM? OP_IDIV: OP_IDIV_UN);
+                       temp->sreg1 = ins->sreg1;
+                       temp->sreg2 = ins->sreg2;
+                       temp->dreg = mono_regstate_next_int (cfg->rs);
+                       mul->sreg1 = temp->dreg;
+                       mul->sreg2 = ins->sreg2;
+                       mul->dreg = mono_regstate_next_int (cfg->rs);
+                       ins->opcode = OP_ISUB;
+                       ins->sreg2 = mul->dreg;
+                       break;
+               }
+               case OP_IADD_IMM:
                case OP_ADD_IMM:
                case OP_ADDCC_IMM:
                        if (!ppc_is_imm16 (ins->inst_imm)) {
-                               NEW_INS (cfg, temp, OP_ICONST);
+                               NEW_INS (cfg,  temp, OP_ICONST);
                                temp->inst_c0 = ins->inst_imm;
                                temp->dreg = mono_regstate_next_int (cfg->rs);
                                ins->sreg2 = temp->dreg;
                                ins->opcode = map_to_reg_reg_op (ins->opcode);
                        }
                        break;
+               case OP_ISUB_IMM:
                case OP_SUB_IMM:
                        if (!ppc_is_imm16 (-ins->inst_imm)) {
                                NEW_INS (cfg, temp, OP_ICONST);
@@ -1757,6 +1976,9 @@ loop_start:
                                ins->opcode = map_to_reg_reg_op (ins->opcode);
                        }
                        break;
+               case OP_IAND_IMM:
+               case OP_IOR_IMM:
+               case OP_IXOR_IMM:
                case OP_AND_IMM:
                case OP_OR_IMM:
                case OP_XOR_IMM:
@@ -1768,6 +1990,8 @@ loop_start:
                                ins->opcode = map_to_reg_reg_op (ins->opcode);
                        }
                        break;
+               case OP_ISBB_IMM:
+               case OP_IADC_IMM:
                case OP_SBB_IMM:
                case OP_SUBCC_IMM:
                case OP_ADC_IMM:
@@ -1778,7 +2002,10 @@ loop_start:
                        ins->opcode = map_to_reg_reg_op (ins->opcode);
                        break;
                case OP_COMPARE_IMM:
-                       if (compare_opcode_is_unsigned (ins->next->opcode)) {
+               case OP_ICOMPARE_IMM:
+                       next = ins->next;
+                       g_assert(next);
+                       if (compare_opcode_is_unsigned (next->opcode)) {
                                if (!ppc_is_uimm16 (ins->inst_imm)) {
                                        NEW_INS (cfg, temp, OP_ICONST);
                                        temp->inst_c0 = ins->inst_imm;
@@ -1796,6 +2023,7 @@ loop_start:
                                }
                        }
                        break;
+               case OP_IMUL_IMM:
                case OP_MUL_IMM:
                        if (ins->inst_imm == 1) {
                                ins->opcode = OP_MOVE;
@@ -1820,6 +2048,13 @@ loop_start:
                                ins->opcode = map_to_reg_reg_op (ins->opcode);
                        }
                        break;
+               case OP_LOCALLOC_IMM:
+                       NEW_INS (cfg, temp, OP_ICONST);
+                       temp->inst_c0 = ins->inst_imm;
+                       temp->dreg = mono_regstate_next_int (cfg->rs);
+                       ins->sreg1 = temp->dreg;
+                       ins->opcode = OP_LOCALLOC;
+                       break;
                case OP_LOAD_MEMBASE:
                case OP_LOADI4_MEMBASE:
                case OP_LOADU4_MEMBASE:
@@ -1874,22 +2109,12 @@ loop_start:
                        goto loop_start;
                }
                last_ins = ins;
-               ins = ins->next;
        }
        bb->last_ins = last_ins;
        bb->max_vreg = cfg->rs->next_vreg;
        
 }
 
-void
-mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
-{
-       if (!bb->code)
-               return;
-       mono_arch_lowering_pass (cfg, bb);
-       mono_local_regalloc (cfg, bb);
-}
-
 static guchar*
 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
 {
@@ -2145,10 +2370,25 @@ ppc_patch (guchar *code, guchar *target)
 //     g_print ("patched with 0x%08x\n", ins);
 }
 
+static guint8*
+emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code)
+{
+       switch (ins->opcode) {
+       case OP_FCALL:
+       case OP_FCALL_REG:
+       case OP_FCALL_MEMBASE:
+               if (ins->dreg != ppc_f1)
+                       ppc_fmr (code, ins->dreg, ppc_f1);
+               break;
+       }
+
+       return code;
+}
+
 void
 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-       MonoInst *ins;
+       MonoInst *ins, *next;
        MonoCallInst *call;
        guint offset;
        guint8 *code = cfg->native_code + cfg->code_len;
@@ -2156,9 +2396,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
        guint last_offset = 0;
        int max_len, cpos;
 
-       if (cfg->opt & MONO_OPT_PEEPHOLE)
-               peephole_pass (cfg, bb);
-
        /* we don't align basic blocks of loops on ppc */
 
        if (cfg->verbose_level > 2)
@@ -2177,8 +2414,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                //x86_inc_mem (code, &cov->data [bb->dfn].count); 
        }
 
-       ins = bb->code;
-       while (ins) {
+       MONO_BB_FOR_EACH_INS (bb, ins) {
                offset = code - cfg->native_code;
 
                max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
@@ -2193,6 +2429,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                mono_debug_record_line_number (cfg, ins, offset);
 
                switch (ins->opcode) {
+               case OP_NOP:
+               case OP_DUMMY_USE:
+               case OP_DUMMY_STORE:
+               case OP_NOT_REACHED:
+               case OP_NOT_NULL:
+                       break;
                case OP_TLS_GET:
                        emit_tls_access (code, ins->dreg, ins->inst_offset);
                        break;
@@ -2241,12 +2483,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_STOREI4_MEMINDEX:
                        ppc_stwx (code, ins->sreg1, ins->sreg2, ins->inst_destbasereg);
                        break;
-               case CEE_LDIND_I:
-               case CEE_LDIND_I4:
-               case CEE_LDIND_U4:
-                       g_assert_not_reached ();
-                       //x86_mov_reg_mem (code, ins->dreg, ins->inst_p0, 4);
-                       break;
                case OP_LOADU4_MEM:
                        g_assert_not_reached ();
                        break;
@@ -2301,26 +2537,30 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_lbzx (code, ins->dreg, ins->sreg2, ins->inst_basereg);
                        ppc_extsb (code, ins->dreg, ins->dreg);
                        break;
-               case CEE_CONV_I1:
+               case OP_ICONV_TO_I1:
                        ppc_extsb (code, ins->dreg, ins->sreg1);
                        break;
-               case CEE_CONV_I2:
+               case OP_ICONV_TO_I2:
                        ppc_extsh (code, ins->dreg, ins->sreg1);
                        break;
-               case CEE_CONV_U1:
+               case OP_ICONV_TO_U1:
                        ppc_rlwinm (code, ins->dreg, ins->sreg1, 0, 24, 31);
                        break;
-               case CEE_CONV_U2:
+               case OP_ICONV_TO_U2:
                        ppc_rlwinm (code, ins->dreg, ins->sreg1, 0, 16, 31);
                        break;
                case OP_COMPARE:
-                       if (ins->next && compare_opcode_is_unsigned (ins->next->opcode))
+               case OP_ICOMPARE:
+                       next = ins->next;
+                       if (next && compare_opcode_is_unsigned (next->opcode))
                                ppc_cmpl (code, 0, 0, ins->sreg1, ins->sreg2);
                        else
                                ppc_cmp (code, 0, 0, ins->sreg1, ins->sreg2);
                        break;
                case OP_COMPARE_IMM:
-                       if (ins->next && compare_opcode_is_unsigned (ins->next->opcode)) {
+               case OP_ICOMPARE_IMM:
+                       next = ins->next;
+                       if (next && compare_opcode_is_unsigned (next->opcode)) {
                                if (ppc_is_uimm16 (ins->inst_imm)) {
                                        ppc_cmpli (code, 0, 0, ins->sreg1, (ins->inst_imm & 0xffff));
                                } else {
@@ -2338,12 +2578,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_break (code);
                        break;
                case OP_ADDCC:
+               case OP_IADDCC:
                        ppc_addc (code, ins->dreg, ins->sreg1, ins->sreg2);
                        break;
-               case CEE_ADD:
+               case OP_IADD:
                        ppc_add (code, ins->dreg, ins->sreg1, ins->sreg2);
                        break;
                case OP_ADC:
+               case OP_IADC:
                        ppc_adde (code, ins->dreg, ins->sreg1, ins->sreg2);
                        break;
                case OP_ADDCC_IMM:
@@ -2354,13 +2596,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        }
                        break;
                case OP_ADD_IMM:
+               case OP_IADD_IMM:
                        if (ppc_is_imm16 (ins->inst_imm)) {
                                ppc_addi (code, ins->dreg, ins->sreg1, ins->inst_imm);
                        } else {
                                g_assert_not_reached ();
                        }
                        break;
-               case CEE_ADD_OVF:
+               case OP_IADD_OVF:
                        /* check XER [0-3] (SO, OV, CA): we can't use mcrxr
                         */
                        ppc_addo (code, ins->dreg, ins->sreg1, ins->sreg2);
@@ -2368,7 +2611,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_andisd (code, ppc_r0, ppc_r0, (1<<14));
                        EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_FALSE, PPC_BR_EQ, "OverflowException");
                        break;
-               case CEE_ADD_OVF_UN:
+               case OP_IADD_OVF_UN:
                        /* check XER [0-3] (SO, OV, CA): we can't use mcrxr
                         */
                        ppc_addco (code, ins->dreg, ins->sreg1, ins->sreg2);
@@ -2376,7 +2619,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_andisd (code, ppc_r0, ppc_r0, (1<<13));
                        EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_FALSE, PPC_BR_EQ, "OverflowException");
                        break;
-               case CEE_SUB_OVF:
+               case OP_ISUB_OVF:
                        /* check XER [0-3] (SO, OV, CA): we can't use mcrxr
                         */
                        ppc_subfo (code, ins->dreg, ins->sreg2, ins->sreg1);
@@ -2384,7 +2627,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_andisd (code, ppc_r0, ppc_r0, (1<<14));
                        EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_FALSE, PPC_BR_EQ, "OverflowException");
                        break;
-               case CEE_SUB_OVF_UN:
+               case OP_ISUB_OVF_UN:
                        /* check XER [0-3] (SO, OV, CA): we can't use mcrxr
                         */
                        ppc_subfc (code, ins->dreg, ins->sreg2, ins->sreg1);
@@ -2425,15 +2668,18 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_TRUE, PPC_BR_EQ, "OverflowException");
                        break;
                case OP_SUBCC:
+               case OP_ISUBCC:
                        ppc_subfc (code, ins->dreg, ins->sreg2, ins->sreg1);
                        break;
-               case CEE_SUB:
+               case OP_ISUB:
                        ppc_subf (code, ins->dreg, ins->sreg2, ins->sreg1);
                        break;
                case OP_SBB:
+               case OP_ISBB:
                        ppc_subfe (code, ins->dreg, ins->sreg2, ins->sreg1);
                        break;
                case OP_SUB_IMM:
+               case OP_ISUB_IMM:
                        // we add the negated value
                        if (ppc_is_imm16 (-ins->inst_imm))
                                ppc_addi (code, ins->dreg, ins->sreg1, -ins->inst_imm);
@@ -2448,11 +2694,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_PPC_SUBFZE:
                        ppc_subfze (code, ins->dreg, ins->sreg1);
                        break;
-               case CEE_AND:
+               case OP_IAND:
                        /* FIXME: the ppc macros as inconsistent here: put dest as the first arg! */
                        ppc_and (code, ins->sreg1, ins->dreg, ins->sreg2);
                        break;
                case OP_AND_IMM:
+               case OP_IAND_IMM:
                        if (!(ins->inst_imm & 0xffff0000)) {
                                ppc_andid (code, ins->sreg1, ins->dreg, ins->inst_imm);
                        } else if (!(ins->inst_imm & 0xffff)) {
@@ -2461,7 +2708,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                g_assert_not_reached ();
                        }
                        break;
-               case CEE_DIV: {
+               case OP_IDIV: {
                        guint32 *divisor_is_m1;
                          /* XER format: SO, OV, CA, reserved [21 bits], count [8 bits]
                          */
@@ -2480,21 +2727,22 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_FALSE, PPC_BR_EQ, "DivideByZeroException");
                        break;
                }
-               case CEE_DIV_UN:
+               case OP_IDIV_UN:
                        ppc_divwuod (code, ins->dreg, ins->sreg1, ins->sreg2);
                        ppc_mfspr (code, ppc_r0, ppc_xer);
                        ppc_andisd (code, ppc_r0, ppc_r0, (1<<14));
                        EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_FALSE, PPC_BR_EQ, "DivideByZeroException");
                        break;
                case OP_DIV_IMM:
-               case CEE_REM:
-               case CEE_REM_UN:
+               case OP_IREM:
+               case OP_IREM_UN:
                case OP_REM_IMM:
                        g_assert_not_reached ();
-               case CEE_OR:
+               case OP_IOR:
                        ppc_or (code, ins->dreg, ins->sreg1, ins->sreg2);
                        break;
                case OP_OR_IMM:
+               case OP_IOR_IMM:
                        if (!(ins->inst_imm & 0xffff0000)) {
                                ppc_ori (code, ins->sreg1, ins->dreg, ins->inst_imm);
                        } else if (!(ins->inst_imm & 0xffff)) {
@@ -2503,9 +2751,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                g_assert_not_reached ();
                        }
                        break;
-               case CEE_XOR:
+               case OP_IXOR:
                        ppc_xor (code, ins->dreg, ins->sreg1, ins->sreg2);
                        break;
+               case OP_IXOR_IMM:
                case OP_XOR_IMM:
                        if (!(ins->inst_imm & 0xffff0000)) {
                                ppc_xori (code, ins->sreg1, ins->dreg, ins->inst_imm);
@@ -2515,36 +2764,40 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                g_assert_not_reached ();
                        }
                        break;
-               case CEE_SHL:
+               case OP_ISHL:
                        ppc_slw (code, ins->sreg1, ins->dreg, ins->sreg2);
                        break;
                case OP_SHL_IMM:
+               case OP_ISHL_IMM:
                        ppc_rlwinm (code, ins->dreg, ins->sreg1, (ins->inst_imm & 0x1f), 0, (31 - (ins->inst_imm & 0x1f)));
                        break;
-               case CEE_SHR:
+               case OP_ISHR:
                        ppc_sraw (code, ins->dreg, ins->sreg1, ins->sreg2);
                        break;
                case OP_SHR_IMM:
+               case OP_ISHR_IMM:
                        ppc_srawi (code, ins->dreg, ins->sreg1, (ins->inst_imm & 0x1f));
                        break;
                case OP_SHR_UN_IMM:
+               case OP_ISHR_UN_IMM:
                        if (ins->inst_imm)
                                ppc_rlwinm (code, ins->dreg, ins->sreg1, (32 - (ins->inst_imm & 0x1f)), (ins->inst_imm & 0x1f), 31);
                        else
                                ppc_mr (code, ins->dreg, ins->sreg1);
                        break;
-               case CEE_SHR_UN:
+               case OP_ISHR_UN:
                        ppc_srw (code, ins->dreg, ins->sreg1, ins->sreg2);
                        break;
-               case CEE_NOT:
+               case OP_INOT:
                        ppc_not (code, ins->dreg, ins->sreg1);
                        break;
-               case CEE_NEG:
+               case OP_INEG:
                        ppc_neg (code, ins->dreg, ins->sreg1);
                        break;
-               case CEE_MUL:
+               case OP_IMUL:
                        ppc_mullw (code, ins->dreg, ins->sreg1, ins->sreg2);
                        break;
+               case OP_IMUL_IMM:
                case OP_MUL_IMM:
                        if (ppc_is_imm16 (ins->inst_imm)) {
                            ppc_mulli (code, ins->dreg, ins->sreg1, ins->inst_imm);
@@ -2552,7 +2805,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                            g_assert_not_reached ();
                        }
                        break;
-               case CEE_MUL_OVF:
+               case OP_IMUL_OVF:
                        /* we annot use mcrxr, since it's not implemented on some processors 
                         * XER format: SO, OV, CA, reserved [21 bits], count [8 bits]
                         */
@@ -2561,7 +2814,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_andisd (code, ppc_r0, ppc_r0, (1<<14));
                        EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_FALSE, PPC_BR_EQ, "OverflowException");
                        break;
-               case CEE_MUL_OVF_UN:
+               case OP_IMUL_OVF_UN:
                        /* we first multiply to get the high word and compare to 0
                         * to set the flags, then the result is discarded and then 
                         * we multiply to get the lower * bits result
@@ -2572,7 +2825,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_mullw (code, ins->dreg, ins->sreg1, ins->sreg2);
                        break;
                case OP_ICONST:
-               case OP_SETREGIMM:
                        ppc_load (code, ins->dreg, ins->inst_c0);
                        break;
                case OP_AOTCONST:
@@ -2580,10 +2832,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_lis (code, ins->dreg, 0);
                        ppc_ori (code, ins->dreg, ins->dreg, 0);
                        break;
-               case CEE_CONV_I4:
-               case CEE_CONV_U4:
+               case OP_ICONV_TO_I4:
+               case OP_ICONV_TO_U4:
                case OP_MOVE:
-               case OP_SETREG:
                        ppc_mr (code, ins->dreg, ins->sreg1);
                        break;
                case OP_SETLRET: {
@@ -2598,7 +2849,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                ppc_mr (code, ppc_r4, saved);
                        break;
                }
-               case OP_SETFREG:
                case OP_FMOVE:
                        ppc_fmr (code, ins->dreg, ins->sreg1);
                        break;
@@ -2668,8 +2918,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_FCALL:
                case OP_LCALL:
                case OP_VCALL:
+               case OP_VCALL2:
                case OP_VOIDCALL:
-               case CEE_CALL:
+               case OP_CALL:
                        call = (MonoCallInst*)ins;
                        if (ins->flags & MONO_INST_HAS_METHOD)
                                mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_METHOD, call->method);
@@ -2683,23 +2934,31 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        } else {
                                ppc_bl (code, 0);
                        }
+                       /* FIXME: this should be handled somewhere else in the new jit */
+                       code = emit_move_return_value (cfg, ins, code);
                        break;
                case OP_FCALL_REG:
                case OP_LCALL_REG:
                case OP_VCALL_REG:
+               case OP_VCALL2_REG:
                case OP_VOIDCALL_REG:
                case OP_CALL_REG:
                        ppc_mtlr (code, ins->sreg1);
                        ppc_blrl (code);
+                       /* FIXME: this should be handled somewhere else in the new jit */
+                       code = emit_move_return_value (cfg, ins, code);
                        break;
                case OP_FCALL_MEMBASE:
                case OP_LCALL_MEMBASE:
                case OP_VCALL_MEMBASE:
+               case OP_VCALL2_MEMBASE:
                case OP_VOIDCALL_MEMBASE:
                case OP_CALL_MEMBASE:
                        ppc_lwz (code, ppc_r0, ins->inst_offset, ins->sreg1);
                        ppc_mtlr (code, ppc_r0);
                        ppc_blrl (code);
+                       /* FIXME: this should be handled somewhere else in the new jit */
+                       code = emit_move_return_value (cfg, ins, code);
                        break;
                case OP_OUTARG:
                        g_assert_not_reached ();
@@ -2743,9 +3002,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_addi (code, ins->dreg, ppc_sp, area_offset);
                        break;
                }
-               case CEE_RET:
-                       ppc_blr (code);
-                       break;
                case OP_THROW: {
                        //ppc_break (code);
                        ppc_mr (code, ppc_r3, ins->sreg1);
@@ -2776,32 +3032,38 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        }
                        break;
                }
-               case OP_START_HANDLER:
+               case OP_START_HANDLER: {
+                       MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
                        ppc_mflr (code, ppc_r0);
-                       if (ppc_is_imm16 (ins->inst_left->inst_offset)) {
-                               ppc_stw (code, ppc_r0, ins->inst_left->inst_offset, ins->inst_left->inst_basereg);
+                       if (ppc_is_imm16 (spvar->inst_offset)) {
+                               ppc_stw (code, ppc_r0, spvar->inst_offset, spvar->inst_basereg);
                        } else {
-                               ppc_load (code, ppc_r11, ins->inst_left->inst_offset);
-                               ppc_stwx (code, ppc_r0, ppc_r11, ins->inst_left->inst_basereg);
+                               ppc_load (code, ppc_r11, spvar->inst_offset);
+                               ppc_stwx (code, ppc_r0, ppc_r11, spvar->inst_basereg);
                        }
                        break;
-               case OP_ENDFILTER:
+               }
+               case OP_ENDFILTER: {
+                       MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
                        if (ins->sreg1 != ppc_r3)
                                ppc_mr (code, ppc_r3, ins->sreg1);
-                       if (ppc_is_imm16 (ins->inst_left->inst_offset)) {
-                               ppc_lwz (code, ppc_r0, ins->inst_left->inst_offset, ins->inst_left->inst_basereg);
+                       if (ppc_is_imm16 (spvar->inst_offset)) {
+                               ppc_lwz (code, ppc_r0, spvar->inst_offset, spvar->inst_basereg);
                        } else {
-                               ppc_load (code, ppc_r11, ins->inst_left->inst_offset);
-                               ppc_lwzx (code, ppc_r0, ins->inst_left->inst_basereg, ppc_r11);
+                               ppc_load (code, ppc_r11, spvar->inst_offset);
+                               ppc_lwzx (code, ppc_r0, spvar->inst_basereg, ppc_r11);
                        }
                        ppc_mtlr (code, ppc_r0);
                        ppc_blr (code);
                        break;
-               case OP_ENDFINALLY:
-                       ppc_lwz (code, ppc_r0, ins->inst_left->inst_offset, ins->inst_left->inst_basereg);
+               }
+               case OP_ENDFINALLY: {
+                       MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
+                       ppc_lwz (code, ppc_r0, spvar->inst_offset, spvar->inst_basereg);
                        ppc_mtlr (code, ppc_r0);
                        ppc_blr (code);
                        break;
+               }
                case OP_CALL_HANDLER: 
                        mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_target_bb);
                        ppc_bl (code, 0);
@@ -2810,9 +3072,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ins->inst_c0 = code - cfg->native_code;
                        break;
                case OP_BR:
-                       //g_print ("target: %p, next: %p, curr: %p, last: %p\n", ins->inst_target_bb, bb->next_bb, ins, bb->last_ins);
-                       //if ((ins->inst_target_bb == bb->next_bb) && ins == bb->last_ins)
-                       //break;
                        if (ins->flags & MONO_INST_BRLABEL) {
                                /*if (ins->inst_i0->inst_c0) {
                                        ppc_b (code, 0);
@@ -2836,18 +3095,23 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_bcctr (code, PPC_BR_ALWAYS, 0);
                        break;
                case OP_CEQ:
+               case OP_ICEQ:
                        ppc_li (code, ins->dreg, 0);
                        ppc_bc (code, PPC_BR_FALSE, PPC_BR_EQ, 2);
                        ppc_li (code, ins->dreg, 1);
                        break;
                case OP_CLT:
                case OP_CLT_UN:
+               case OP_ICLT:
+               case OP_ICLT_UN:
                        ppc_li (code, ins->dreg, 1);
                        ppc_bc (code, PPC_BR_TRUE, PPC_BR_LT, 2);
                        ppc_li (code, ins->dreg, 0);
                        break;
                case OP_CGT:
                case OP_CGT_UN:
+               case OP_ICGT:
+               case OP_ICGT_UN:
                        ppc_li (code, ins->dreg, 1);
                        ppc_bc (code, PPC_BR_TRUE, PPC_BR_GT, 2);
                        ppc_li (code, ins->dreg, 0);
@@ -2864,6 +3128,18 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_COND_EXC_LE_UN:
                        EMIT_COND_SYSTEM_EXCEPTION (ins->opcode - OP_COND_EXC_EQ, ins->inst_p1);
                        break;
+               case OP_COND_EXC_IEQ:
+               case OP_COND_EXC_INE_UN:
+               case OP_COND_EXC_ILT:
+               case OP_COND_EXC_ILT_UN:
+               case OP_COND_EXC_IGT:
+               case OP_COND_EXC_IGT_UN:
+               case OP_COND_EXC_IGE:
+               case OP_COND_EXC_IGE_UN:
+               case OP_COND_EXC_ILE:
+               case OP_COND_EXC_ILE_UN:
+                       EMIT_COND_SYSTEM_EXCEPTION (ins->opcode - OP_COND_EXC_IEQ, ins->inst_p1);
+                       break;
                case OP_COND_EXC_C:
                        /* check XER [0-3] (SO, OV, CA): we can't use mcrxr
                         */
@@ -2879,17 +3155,17 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_COND_EXC_NO:
                        g_assert_not_reached ();
                        break;
-               case CEE_BEQ:
-               case CEE_BNE_UN:
-               case CEE_BLT:
-               case CEE_BLT_UN:
-               case CEE_BGT:
-               case CEE_BGT_UN:
-               case CEE_BGE:
-               case CEE_BGE_UN:
-               case CEE_BLE:
-               case CEE_BLE_UN:
-                       EMIT_COND_BRANCH (ins, ins->opcode - CEE_BEQ);
+               case OP_IBEQ:
+               case OP_IBNE_UN:
+               case OP_IBLT:
+               case OP_IBLT_UN:
+               case OP_IBGT:
+               case OP_IBGT_UN:
+               case OP_IBGE:
+               case OP_IBGE_UN:
+               case OP_IBLE:
+               case OP_IBLE_UN:
+                       EMIT_COND_BRANCH (ins, ins->opcode - OP_IBEQ);
                        break;
 
                /* floating point opcodes */
@@ -2971,6 +3247,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        g_assert_not_reached ();
                        /* Implemented as helper calls */
                        break;
+               case OP_LCONV_TO_OVF_I4_2:
                case OP_LCONV_TO_OVF_I: {
                        guint32 *negative_branch, *msword_positive_branch, *msword_negative_branch, *ovf_ex_target;
                        // Check if its negative
@@ -3097,6 +3374,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_rlwinmd (code, ins->sreg1, ins->sreg1, 1, 31, 31);
                        EMIT_COND_SYSTEM_EXCEPTION (CEE_BEQ - CEE_BEQ, "ArithmeticException");
                        break;
+               case OP_JUMP_TABLE:
+                       mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
+                       ppc_load (code, ins->dreg, 0x0f0f0f0f);
+                       break;
                }
                default:
                        g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
@@ -3113,8 +3394,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 
                last_ins = ins;
                last_offset = offset;
-               
-               ins = ins->next;
        }
 
        cfg->code_len = code - cfg->native_code;
@@ -3291,16 +3570,14 @@ mono_arch_emit_prolog (MonoCompile *cfg)
         */
        max_offset = 0;
        for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-               MonoInst *ins = bb->code;
+               MonoInst *ins;
                bb->max_offset = max_offset;
 
                if (cfg->prof_options & MONO_PROFILE_COVERAGE)
                        max_offset += 6; 
 
-               while (ins) {
+               MONO_BB_FOR_EACH_INS (bb, ins)
                        max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
-                       ins = ins->next;
-               }
        }
 
        /* load arguments allocated to register from the stack */
@@ -3941,7 +4218,7 @@ mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, int this_re
        /* add the this argument */
        if (this_reg != -1) {
                MonoInst *this;
-               MONO_INST_NEW (cfg, this, OP_SETREG);
+               MONO_INST_NEW (cfg, this, OP_MOVE);
                this->type = this_type;
                this->sreg1 = this_reg;
                this->dreg = mono_regstate_next_int (cfg->rs);
@@ -3951,7 +4228,7 @@ mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, int this_re
 
        if (vt_reg != -1) {
                MonoInst *vtarg;
-               MONO_INST_NEW (cfg, vtarg, OP_SETREG);
+               MONO_INST_NEW (cfg, vtarg, OP_MOVE);
                vtarg->type = STACK_MP;
                vtarg->sreg1 = vt_reg;
                vtarg->dreg = mono_regstate_next_int (cfg->rs);
@@ -4062,9 +4339,9 @@ mono_arch_find_imt_method (gpointer *regs, guint8 *code)
 }
 
 MonoObject*
-mono_arch_find_this_argument (gpointer *regs, MonoMethod *method)
+mono_arch_find_this_argument (gpointer *regs, MonoMethod *method, MonoGenericSharingContext *gsctx)
 {
-       return mono_arch_get_this_arg_from_call (mono_method_signature (method), (gssize*)regs, NULL);
+       return mono_arch_get_this_arg_from_call (gsctx, mono_method_signature (method), (gssize*)regs, NULL);
 }
 #endif
 
@@ -4073,10 +4350,6 @@ mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethod
 {
        MonoInst *ins = NULL;
 
-       if (cmethod->klass == mono_defaults.thread_class &&
-                       strcmp (cmethod->name, "MemoryBarrier") == 0) {
-               MONO_INST_NEW (cfg, ins, OP_MEMORY_BARRIER);
-       }
        /*if (cmethod->klass == mono_defaults.math_class) {
                if (strcmp (cmethod->name, "Sqrt") == 0) {
                        MONO_INST_NEW (cfg, ins, OP_SQRT);
@@ -4086,6 +4359,13 @@ mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethod
        return ins;
 }
 
+MonoInst*
+mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
+{
+       /* FIXME: */
+       return NULL;
+}
+
 gboolean
 mono_arch_print_tree (MonoInst *tree, int arity)
 {
@@ -4119,3 +4399,9 @@ mono_arch_get_thread_intrinsic (MonoCompile* cfg)
        return ins;
 }
 
+gpointer
+mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
+{
+       /* FIXME: implement */
+       g_assert_not_reached ();
+}