Tue Jan 16 12:42:40 CET 2007 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / mini / mini.c
index 6671472c8a0c7947d145ec6fd09e759b8451a583..e6127e79b86457088e44515b7cfb70abf6566ca2 100644 (file)
@@ -228,13 +228,35 @@ get_method_from_ip (void *ip)
        return res;
 }
 
+/** 
+ * mono_pmip:
+ * @ip: an instruction pointer address
+ *
+ * This method is used from a debugger to get the name of the
+ * method at address @ip.   This routine is typically invoked from
+ * a debugger like this:
+ *
+ * (gdb) print mono_pmip ($pc)
+ *
+ * Returns: the name of the method at address @ip.
+ */
 G_GNUC_UNUSED char *
 mono_pmip (void *ip)
 {
        return get_method_from_ip (ip);
 }
 
-/* debug function */
+/** 
+ * mono_print_method_from_ip
+ * @ip: an instruction pointer address
+ *
+ * This method is used from a debugger to get the name of the
+ * method at address @ip.
+ *
+ * This prints the name of the method at address @ip in the standard
+ * output.  Unlike mono_pmip which returns a string, this routine
+ * prints the value on the standard output. 
+ */
 void
 mono_print_method_from_ip (void *ip)
 {
@@ -866,9 +888,11 @@ mono_find_block_region (MonoCompile *cfg, int offset)
                        return ((i + 1) << 8) | MONO_REGION_FILTER | clause->flags;
                           
                if (MONO_OFFSET_IN_HANDLER (clause, offset)) {
-                       if (clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY)
+                       if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY)
                                return ((i + 1) << 8) | MONO_REGION_FINALLY | clause->flags;
-                       else
+                       else if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT)
+                               return ((i + 1) << 8) | MONO_REGION_FAULT | clause->flags;
+                       else if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE)
                                return ((i + 1) << 8) | MONO_REGION_CATCH | clause->flags;
                }
        }
@@ -1272,7 +1296,7 @@ ovf3ops_op_map [STACK_MAX] = {
 /* handles from CEE_CEQ to CEE_CLT_UN */
 static const guint16
 ceqops_op_map [STACK_MAX] = {
-       0, 0, OP_LCEQ-CEE_CEQ, OP_PCEQ-CEE_CEQ, OP_FCEQ-CEE_CEQ, OP_LCEQ-CEE_CEQ
+       0, 0, OP_LCEQ-OP_CEQ, OP_PCEQ-OP_CEQ, OP_FCEQ-OP_CEQ, OP_LCEQ-OP_CEQ
 };
 
 /*
@@ -1318,11 +1342,15 @@ type_from_op (MonoInst *ins) {
                        ins->opcode = OP_LCOMPARE;
                return;
        case OP_CEQ:
+               ins->type = bin_comp_table [ins->inst_i0->type] [ins->inst_i1->type] ? STACK_I4: STACK_INV;
+               ins->opcode += ceqops_op_map [ins->inst_i0->type];
+               return;
+               
        case OP_CGT:
        case OP_CGT_UN:
        case OP_CLT:
        case OP_CLT_UN:
-               ins->type = bin_comp_table [ins->inst_i0->type] [ins->inst_i1->type] ? STACK_I4: STACK_INV;
+               ins->type = (bin_comp_table [ins->inst_i0->type] [ins->inst_i1->type] & 1) ? STACK_I4: STACK_INV;
                ins->opcode += ceqops_op_map [ins->inst_i0->type];
                return;
        /* unops */
@@ -1645,16 +1673,12 @@ type_from_stack_type (MonoInst *ins) {
        case STACK_R8: return &mono_defaults.double_class->byval_arg;
        case STACK_MP:
                /* 
-                * FIXME: This doesn't work because mono_class_from_mono_type ()
-                * returns the original klass for a byref type, not a 'byref' class,
-                * causing the JIT to create variables with the wrong type, for
-                * example.
+                * this if used to be commented without any specific reason, but
+                * it breaks #80235 when commented
                 */
-               /*
                if (ins->klass)
                        return &ins->klass->this_arg;
                else
-               */
                        return &mono_defaults.object_class->this_arg;
        case STACK_OBJ: return &mono_defaults.object_class->byval_arg;
        case STACK_VTYPE: return &ins->klass->byval_arg;
@@ -2410,13 +2434,31 @@ mono_emit_call_args (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethodSignatu
        MonoInst *arg;
 
        MONO_INST_NEW_CALL (cfg, call, ret_type_to_call_opcode (sig->ret, calli, virtual));
-       
+
+#ifdef MONO_ARCH_SOFT_FLOAT
+       /* we need to convert the r4 value to an int value */
+       {
+               int i;
+               for (i = 0; i < sig->param_count; ++i) {
+                       if (sig->params [i]->type == MONO_TYPE_R4) {
+                               MonoInst *iargs [1];
+                               int temp;
+                               iargs [0] = args [i + sig->hasthis];
+
+                               temp = mono_emit_jit_icall (cfg, bblock, mono_fload_r4_arg, iargs, ip);
+                               NEW_TEMPLOAD (cfg, arg, temp);
+                               args [i + sig->hasthis] = arg;
+                       }
+               }
+       }
+#endif
+
        call->inst.cil_code = ip;
        call->args = args;
        call->signature = sig;
        call = mono_arch_call_opcode (cfg, bblock, call, virtual);
        type_to_eval_stack_type (sig->ret, &call->inst);
-       
+
        for (arg = call->out_args; arg;) {
                MonoInst *narg = arg->next;
                arg->next = NULL;
@@ -2583,7 +2625,7 @@ mono_emulate_opcode (MonoCompile *cfg, MonoInst *tree, MonoInst **iargs, MonoJit
 }
 
 static MonoMethodSignature *
-mono_get_element_address_signature (int arity)
+mono_get_array_new_va_signature (int arity)
 {
        static GHashTable *sighash = NULL;
        MonoMethodSignature *res;
@@ -2594,7 +2636,7 @@ mono_get_element_address_signature (int arity)
                sighash = g_hash_table_new (NULL, NULL);
        }
        else if ((res = g_hash_table_lookup (sighash, GINT_TO_POINTER (arity)))) {
-               LeaveCriticalSection (&jit_mutex);
+               mono_jit_unlock ();
                return res;
        }
 
@@ -2605,17 +2647,14 @@ mono_get_element_address_signature (int arity)
        /* Only set this only some archs since not all backends can handle varargs+pinvoke */
        res->call_convention = MONO_CALL_VARARG;
 #endif
-       res->params [0] = &mono_defaults.array_class->byval_arg; 
 
 #ifdef PLATFORM_WIN32
-       /* 
-        * The default pinvoke calling convention is STDCALL but we need CDECL.
-        */
        res->call_convention = MONO_CALL_C;
 #endif
 
-       for (i = 1; i <= arity; i++)
-               res->params [i] = &mono_defaults.int_class->byval_arg;
+       res->params [0] = &mono_defaults.int_class->byval_arg;  
+       for (i = 0; i < arity; i++)
+               res->params [i + 1] = &mono_defaults.int_class->byval_arg;
 
        res->ret = &mono_defaults.int_class->byval_arg;
 
@@ -2625,46 +2664,56 @@ mono_get_element_address_signature (int arity)
        return res;
 }
 
-static MonoMethodSignature *
-mono_get_array_new_va_signature (int arity)
+#ifdef MONO_ARCH_SOFT_FLOAT
+static void
+handle_store_float (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *ptr, MonoInst *val, const unsigned char *ip)
 {
-       static GHashTable *sighash = NULL;
-       MonoMethodSignature *res;
-       int i;
+       MonoInst *iargs [2];
+       iargs [0] = val;
+       iargs [1] = ptr;
 
-       mono_jit_lock ();
-       if (!sighash) {
-               sighash = g_hash_table_new (NULL, NULL);
-       }
-       else if ((res = g_hash_table_lookup (sighash, GINT_TO_POINTER (arity)))) {
-               mono_jit_unlock ();
-               return res;
-       }
+       mono_emit_jit_icall (cfg, bblock, mono_fstore_r4, iargs, ip);
+}
 
-       res = mono_metadata_signature_alloc (mono_defaults.corlib, arity + 1);
+static int
+handle_load_float (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *ptr, const unsigned char *ip)
+{
+       MonoInst *iargs [1];
+       iargs [0] = ptr;
 
-       res->pinvoke = 1;
-#ifdef MONO_ARCH_VARARG_ICALLS
-       /* Only set this only some archs since not all backends can handle varargs+pinvoke */
-       res->call_convention = MONO_CALL_VARARG;
-#endif
+       return mono_emit_jit_icall (cfg, bblock, mono_fload_r4, iargs, ip);
+}
 
-#ifdef PLATFORM_WIN32
-       res->call_convention = MONO_CALL_C;
+#define LDLOC_SOFT_FLOAT(cfg,ins,idx,ip) do {\
+               if (header->locals [(idx)]->type == MONO_TYPE_R4 && !header->locals [(idx)]->byref) {   \
+                       int temp;       \
+                       NEW_LOCLOADA (cfg, (ins), (idx));       \
+                       temp = handle_load_float (cfg, bblock, (ins), (ip));    \
+                       NEW_TEMPLOAD (cfg, (ins), temp);        \
+               }       \
+       } while (0)
+#define STLOC_SOFT_FLOAT(cfg,ins,idx,ip) do {\
+               if (header->locals [(idx)]->type == MONO_TYPE_R4 && !header->locals [(idx)]->byref) {   \
+                       int temp;       \
+                       NEW_LOCLOADA (cfg, (ins), (idx));       \
+                       handle_store_float (cfg, bblock, (ins), *sp, (ip));     \
+                       MONO_INST_NEW (cfg, (ins), CEE_NOP);    \
+               }       \
+       } while (0)
+#define LDARG_SOFT_FLOAT(cfg,ins,idx,ip) do {\
+               if (param_types [(idx)]->type == MONO_TYPE_R4 && !param_types [(idx)]->byref) { \
+                       int temp;       \
+                       NEW_ARGLOADA (cfg, (ins), (idx));       \
+                       temp = handle_load_float (cfg, bblock, (ins), (ip));    \
+                       NEW_TEMPLOAD (cfg, (ins), temp);        \
+               }       \
+       } while (0)
+#else
+#define LDLOC_SOFT_FLOAT(cfg,ins,idx,ip)
+#define STLOC_SOFT_FLOAT(cfg,ins,idx,ip)
+#define LDARG_SOFT_FLOAT(cfg,ins,idx,ip)
 #endif
 
-       res->params [0] = &mono_defaults.int_class->byval_arg;  
-       for (i = 0; i < arity; i++)
-               res->params [i + 1] = &mono_defaults.int_class->byval_arg;
-
-       res->ret = &mono_defaults.int_class->byval_arg;
-
-       g_hash_table_insert (sighash, GINT_TO_POINTER (arity), res);
-       mono_jit_unlock ();
-
-       return res;
-}
-
 static MonoMethod*
 get_memcpy_method (void)
 {
@@ -2866,6 +2915,11 @@ handle_box (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *val, const gucha
        vstore->inst_left = add;
        vstore->inst_right = val;
 
+#ifdef MONO_ARCH_SOFT_FLOAT
+       if (vstore->opcode == CEE_STIND_R4) {
+               handle_store_float (cfg, bblock, add, val, ip);
+       } else
+#endif
        if (vstore->opcode == CEE_STOBJ) {
                handle_stobj (cfg, bblock, add, val, ip, klass, FALSE, FALSE, TRUE);
        } else
@@ -2978,6 +3032,11 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
                if (MONO_TYPE_ISSTRUCT (signature->params [i])) {
                        return FALSE;
                }
+#ifdef MONO_ARCH_SOFT_FLOAT
+               /* this complicates things, fix later */
+               if (signature->params [i]->type == MONO_TYPE_R4)
+                       return FALSE;
+#endif
        }
 
        /*
@@ -3053,10 +3112,8 @@ mini_get_ldelema_ins (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethod *cmet
 {
        int temp, rank;
        MonoInst *addr;
-       MonoMethodSignature *esig;
-       char icall_name [256];
-       char *name;
-       MonoJitICallInfo *info;
+       MonoMethod *addr_method;
+       int element_size;
 
        rank = mono_method_signature (cmethod)->param_count - (is_set? 1: 0);
 
@@ -3086,33 +3143,20 @@ mini_get_ldelema_ins (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethod *cmet
 #endif
        }
 
-       /* Need to register the icall so it gets an icall wrapper */
-       sprintf (icall_name, "ves_array_element_address_%d", rank);
-
-       mono_jit_lock ();
-       info = mono_find_jit_icall_by_name (icall_name);
-       if (info == NULL) {
-               esig = mono_get_element_address_signature (rank);
-               name = g_strdup (icall_name);
-               info = mono_register_jit_icall (ves_array_element_address, name, esig, FALSE);
-
-               g_hash_table_insert (jit_icall_name_hash, name, name);
-       }
-       mono_jit_unlock ();
-
-       /* FIXME: This uses info->sig, but it should use the signature of the wrapper */
-       temp = mono_emit_native_call (cfg, bblock, mono_icall_get_wrapper (info), info->sig, sp, ip, FALSE, FALSE);
-       cfg->flags |= MONO_CFG_HAS_VARARGS;
-
+       element_size = mono_class_array_element_size (cmethod->klass->element_class);
+       addr_method = mono_marshal_get_array_address (rank, element_size);
+       temp = mono_emit_method_call_spilled (cfg, bblock, addr_method, addr_method->signature, sp, ip, NULL);
        NEW_TEMPLOAD (cfg, addr, temp);
        return addr;
+
 }
 
-MonoJitICallInfo **emul_opcode_map = NULL;
+static MonoJitICallInfo **emul_opcode_map = NULL;
 
 MonoJitICallInfo *
 mono_find_jit_opcode_emulation (int opcode)
 {
+       g_assert (opcode >= 0 && opcode <= OP_LAST);
        if  (emul_opcode_map)
                return emul_opcode_map [opcode];
        else
@@ -3211,6 +3255,12 @@ mini_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSigna
                store->inst_left = args [2];
                store->inst_right = load;
                return store;
+       } else if (cmethod->klass->image == mono_defaults.corlib) {
+               if (cmethod->name [0] == 'B' && strcmp (cmethod->name, "Break") == 0
+                               && strcmp (cmethod->klass->name, "Debugger") == 0) {
+                       MONO_INST_NEW (cfg, ins, CEE_BREAK);
+                       return ins;
+               }
        }
 
        return mono_arch_get_inst_for_method (cfg, cmethod, fsig, args);
@@ -3424,6 +3474,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
 #define CHECK_LOCAL(num) if ((unsigned)(num) >= (unsigned)header->num_locals) UNVERIFIED
 #define CHECK_OPSIZE(size) if (ip + size > end) UNVERIFIED
 #define CHECK_UNVERIFIABLE(cfg) if (cfg->unverifiable) UNVERIFIED
+#define CHECK_TYPELOAD(klass) if (!(klass) || (klass)->exception_type) {cfg->exception_ptr = klass; goto load_error;}
 
 /* offset from br.s -> br like opcodes */
 #define BIG_BRANCH_OFFSET 13
@@ -3717,6 +3768,68 @@ can_access_method (MonoMethod *method, MonoMethod *called)
        return can;
 }
 
+/*
+ * Check that the IL instructions at ip are the array initialization
+ * sequence and return the pointer to the data and the size.
+ */
+static const char*
+initialize_array_data (MonoMethod *method, gboolean aot, unsigned char *ip, MonoInst *newarr, int *out_size)
+{
+       /*
+        * newarr[System.Int32]
+        * dup
+        * ldtoken field valuetype ...
+        * call void class [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
+        */
+       if (ip [0] == CEE_DUP && ip [1] == CEE_LDTOKEN && ip [5] == 0x4 && ip [6] == CEE_CALL) {
+               MonoClass *klass = newarr->inst_newa_class;
+               guint32 token = read32 (ip + 7);
+               guint32 rva, field_index;
+               const char *data_ptr;
+               int size = 0;
+               MonoMethod *cmethod;
+
+               if (newarr->inst_newa_len->opcode != OP_ICONST)
+                       return NULL;
+               cmethod = mini_get_method (method, token, NULL, NULL);
+               if (strcmp (cmethod->name, "InitializeArray") || strcmp (cmethod->klass->name, "RuntimeHelpers") || cmethod->klass->image != mono_defaults.corlib)
+                       return NULL;
+               switch (mono_type_get_underlying_type (&klass->byval_arg)->type) {
+               case MONO_TYPE_BOOLEAN:
+               case MONO_TYPE_I1:
+               case MONO_TYPE_U1:
+                       size = 1; break;
+               /* we need to swap on big endian, so punt. Should we handle R4 and R8 as well? */
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+               case MONO_TYPE_CHAR:
+               case MONO_TYPE_I2:
+               case MONO_TYPE_U2:
+                       size = 2; break;
+               case MONO_TYPE_I4:
+               case MONO_TYPE_U4:
+                       size = 4; break;
+               case MONO_TYPE_I8:
+               case MONO_TYPE_U8:
+                       size = 8; break;
+#endif
+               default:
+                       return NULL;
+               }
+               size *= newarr->inst_newa_len->inst_c0;
+               *out_size = size;
+               /*g_print ("optimized in %s: size: %d, numelems: %d\n", method->name, size, newarr->inst_newa_len->inst_c0);*/
+               field_index = read32 (ip + 2) & 0xffffff;
+               mono_metadata_field_info (method->klass->image, field_index - 1, NULL, &rva, NULL);
+               data_ptr = mono_image_rva_map (method->klass->image, rva);
+               /*g_print ("field: 0x%08x, rva: %d, rva_ptr: %p\n", read32 (ip + 2), rva, data_ptr);*/
+               /* for aot code we do the lookup on load */
+               if (aot && data_ptr)
+                       return GUINT_TO_POINTER (rva);
+               return data_ptr;
+       }
+       return NULL;
+}
+
 /*
  * mono_method_to_ir: translates IL into basic blocks containing trees
  */
@@ -3780,7 +3893,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        mono_jit_stats.cil_code_size += header->code_size;
 
        if (sig->is_inflated)
-               generic_context = ((MonoMethodInflated *) method)->context;
+               generic_context = mono_method_get_context (method);
        else if (generic_container)
                generic_context = &generic_container->context;
 
@@ -3840,7 +3953,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                tblock->flags |= BB_EXCEPTION_DEAD_OBJ;
 
                        if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY ||
-                           clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
+                           clause->flags == MONO_EXCEPTION_CLAUSE_FILTER ||
+                           clause->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
                                MONO_INST_NEW (cfg, ins, OP_START_HANDLER);
                                MONO_ADD_INS (tblock, ins);
 
@@ -4128,6 +4242,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        n = (*ip)-CEE_LDARG_0;
                        CHECK_ARG (n);
                        NEW_ARGLOAD (cfg, ins, n);
+                       LDARG_SOFT_FLOAT (cfg, ins, n, ip);
                        ins->cil_code = ip++;
                        *sp++ = ins;
                        break;
@@ -4139,6 +4254,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        n = (*ip)-CEE_LDLOC_0;
                        CHECK_LOCAL (n);
                        NEW_LOCLOAD (cfg, ins, n);
+                       LDLOC_SOFT_FLOAT (cfg, ins, n, ip);
                        ins->cil_code = ip++;
                        *sp++ = ins;
                        break;
@@ -4155,6 +4271,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ins->cil_code = ip;
                        if (!dont_verify_stloc && target_type_is_incompatible (cfg, header->locals [n], *sp))
                                UNVERIFIED;
+                       STLOC_SOFT_FLOAT (cfg, ins, n, ip);
                        if (ins->opcode == CEE_STOBJ) {
                                NEW_LOCLOADA (cfg, ins, n);
                                handle_stobj (cfg, bblock, ins, *sp, ip, ins->klass, FALSE, FALSE, FALSE);
@@ -4168,6 +4285,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_STACK_OVF (1);
                        CHECK_ARG (ip [1]);
                        NEW_ARGLOAD (cfg, ins, ip [1]);
+                       LDARG_SOFT_FLOAT (cfg, ins, ip [1], ip);
                        ins->cil_code = ip;
                        *sp++ = ins;
                        ip += 2;
@@ -4203,6 +4321,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_STACK_OVF (1);
                        CHECK_LOCAL (ip [1]);
                        NEW_LOCLOAD (cfg, ins, ip [1]);
+                       LDLOC_SOFT_FLOAT (cfg, ins, ip [1], ip);
                        ins->cil_code = ip;
                        *sp++ = ins;
                        ip += 2;
@@ -4226,6 +4345,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ins->cil_code = ip;
                        if (!dont_verify_stloc && target_type_is_incompatible (cfg, header->locals [ip [1]], *sp))
                                UNVERIFIED;
+                       STLOC_SOFT_FLOAT (cfg, ins, ip [1], ip);
                        if (ins->opcode == CEE_STOBJ) {
                                NEW_LOCLOADA (cfg, ins, ip [1]);
                                handle_stobj (cfg, bblock, ins, *sp, ip, ins->klass, FALSE, FALSE, FALSE);
@@ -4549,7 +4669,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                NEW_TEMPLOAD (cfg, iargs [0], this_temp->inst_c0);
                                NEW_PCONST (cfg, iargs [1], cmethod);
-                               NEW_PCONST (cfg, iargs [2], ((MonoMethodInflated *) cmethod)->context);
+                               NEW_PCONST (cfg, iargs [2], mono_method_get_context (cmethod));
                                NEW_TEMPLOADA (cfg, iargs [3], this_arg_temp->inst_c0);
                                temp = mono_emit_jit_icall (cfg, bblock, mono_helper_compile_generic_method, iargs, ip);
 
@@ -4898,7 +5018,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                sp -= 2;
                                ins->inst_left = sp [0];
                                ins->inst_right = sp [1];
+                               ins->type = STACK_I4;
                                *sp++ = emit_tree (cfg, bblock, ins, ins->cil_code);
+                               MONO_INST_NEW (cfg, ins, CEE_BRTRUE);
                                ADD_UNCOND (TRUE);
                        } else {
                                ADD_BINCOND (NULL);
@@ -4972,7 +5094,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                sp -= 2;
                                ins->inst_left = sp [0];
                                ins->inst_right = sp [1];
+                               ins->type = STACK_I4;
                                *sp++ = emit_tree (cfg, bblock, ins, ins->cil_code);
+                               MONO_INST_NEW (cfg, ins, CEE_BRTRUE);
                                ADD_UNCOND (TRUE);
                        } else {
                                ADD_BINCOND (NULL);
@@ -5044,6 +5168,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ins_flag = 0;
                        if (ins->type == STACK_OBJ)
                                ins->klass = mono_defaults.object_class;
+#ifdef MONO_ARCH_SOFT_FLOAT
+                       if (*ip == CEE_LDIND_R4) {
+                               int temp;
+                               --sp;
+                               temp = handle_load_float (cfg, bblock, ins->inst_i0, ip);
+                               NEW_TEMPLOAD (cfg, *sp, temp);
+                               sp++;
+                       }
+#endif
                        ++ip;
                        break;
                case CEE_STIND_REF:
@@ -5054,6 +5187,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                case CEE_STIND_R4:
                case CEE_STIND_R8:
                        CHECK_STACK (2);
+#ifdef MONO_ARCH_SOFT_FLOAT
+                       if (*ip == CEE_STIND_R4) {
+                               sp -= 2;
+                               handle_store_float (cfg, bblock, sp [0], sp [1], ip);
+                               ip++;
+                               break;
+                       }
+#endif
 #if HAVE_WRITE_BARRIERS
                        if (*ip == CEE_STIND_REF && method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER) {
                                /* insert call to write barrier */
@@ -5204,8 +5345,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_STACK (2);
                        token = read32 (ip + 1);
                        klass = mini_get_class (method, token, generic_context);
-                       if (!klass)
-                               goto load_error;
+                       CHECK_TYPELOAD (klass);
                        sp -= 2;
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                MonoInst *store, *load;
@@ -5255,8 +5395,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        --sp;
                        token = read32 (ip + 1);
                        klass = mini_get_class (method, token, generic_context);
-                       if (!klass)
-                               goto load_error;
+                       CHECK_TYPELOAD (klass);
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                MONO_INST_NEW (cfg, ins, CEE_LDIND_REF);
                                ins->cil_code = ip;
@@ -5523,8 +5662,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
                        klass = mini_get_class (method, token, generic_context);
-                       if (!klass)
-                               goto load_error;
+                       CHECK_TYPELOAD (klass);
                        if (sp [0]->type != STACK_OBJ)
                                UNVERIFIED;
 
@@ -5580,8 +5718,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
                        klass = mini_get_class (method, token, generic_context);
-                       if (!klass)
-                               goto load_error;
+                       CHECK_TYPELOAD (klass);
 
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                /* CASTCLASS */
@@ -5682,8 +5819,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
                        klass = mini_get_class (method, token, generic_context);
-                       if (!klass)
-                               goto load_error;
+                       CHECK_TYPELOAD (klass);
 
                        if (mono_class_is_nullable (klass)) {
                                int v = handle_unbox_nullable (cfg, bblock, *sp, ip, klass);
@@ -5720,8 +5856,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
                        klass = mini_get_class (method, token, generic_context);
-                       if (!klass)
-                               goto load_error;
+                       CHECK_TYPELOAD (klass);
                        if (sp [0]->type != STACK_OBJ)
                                UNVERIFIED;
 
@@ -5870,6 +6005,17 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        iargs [0] = ins;
                                        iargs [1] = sp [1];
                                        mono_emit_method_call_spilled (cfg, bblock, write_barrier, mono_method_signature (write_barrier), iargs, ip, NULL);
+#endif
+#ifdef MONO_ARCH_SOFT_FLOAT
+                               } else if (mono_type_to_stind (field->type) == CEE_STIND_R4) {
+                                       NEW_ICONST (cfg, offset_ins, foffset);
+                                       MONO_INST_NEW (cfg, ins, OP_PADD);
+                                       ins->cil_code = ip;
+                                       ins->inst_left = *sp;
+                                       ins->inst_right = offset_ins;
+                                       ins->type = STACK_MP;
+                                       ins->klass = mono_defaults.object_class;
+                                       handle_store_float (cfg, bblock, ins, sp [1], ip);
 #endif
                                } else {
                                        MonoInst *store;
@@ -5950,6 +6096,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                load->inst_left = ins;
                                                load->flags |= ins_flag;
                                                ins_flag = 0;
+#ifdef MONO_ARCH_SOFT_FLOAT
+                                               if (mono_type_to_ldind (field->type) == CEE_LDIND_R4) {
+                                                       int temp;
+                                                       temp = handle_load_float (cfg, bblock, ins, ip);
+                                                       NEW_TEMPLOAD (cfg, *sp, temp);
+                                                       sp++;
+                                               } else
+#endif
                                                *sp++ = load;
                                        }
                                }
@@ -6158,8 +6312,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
                        klass = mini_get_class (method, token, generic_context);
-                       if (!klass)
-                               goto load_error;
+                       CHECK_TYPELOAD (klass);
                        n = mono_type_to_stind (&klass->byval_arg);
                        if (n == CEE_STOBJ) {
                                handle_stobj (cfg, bblock, sp [0], sp [1], ip, klass, FALSE, FALSE, TRUE);
@@ -6185,8 +6338,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
                        klass = mini_get_class (method, token, generic_context);
-                       if (!klass)
-                               goto load_error;
+                       CHECK_TYPELOAD (klass);
 
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                *sp++ = val;
@@ -6257,8 +6409,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        mono_get_got_var (cfg);
 
                        klass = mini_get_class (method, token, generic_context);
-                       if (!klass)
-                               goto load_error;
+                       CHECK_TYPELOAD (klass);
                        ins->inst_newa_class = klass;
                        ins->inst_newa_len = *sp;
                        ins->type = STACK_OBJ;
@@ -6271,11 +6422,40 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                         */
                        if (1) {
                                MonoInst *store, *temp, *load;
+                               const char *data_ptr;
+                               int data_size = 0;
                                --sp;
                                temp = mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL);
                                NEW_TEMPSTORE (cfg, store, temp->inst_c0, ins);
                                store->cil_code = ins->cil_code;
                                MONO_ADD_INS (bblock, store);
+                               /* 
+                                * we inline/optimize the initialization sequence if possible.
+                                * we should also allocate the array as not cleared, since we spend as much time clearing to 0 as initializing
+                                * for small sizes open code the memcpy
+                                * ensure the rva field is big enough
+                                */
+                               if ((cfg->opt & MONO_OPT_INTRINS) && ip_in_bb (cfg, bblock, ip + 6) && (data_ptr = initialize_array_data (method, cfg->compile_aot, ip, ins, &data_size))) {
+                                       MonoMethod *memcpy_method = get_memcpy_method ();
+                                       MonoInst *data_offset, *add;
+                                       MonoInst *iargs [3];
+                                       NEW_ICONST (cfg, iargs [2], data_size);
+                                       NEW_TEMPLOAD (cfg, load, temp->inst_c0);
+                                       load->cil_code = ins->cil_code;
+                                       NEW_ICONST (cfg, data_offset, G_STRUCT_OFFSET (MonoArray, vector));
+                                       MONO_INST_NEW (cfg, add, OP_PADD);
+                                       add->inst_left = load;
+                                       add->inst_right = data_offset;
+                                       add->cil_code = ip;
+                                       iargs [0] = add;
+                                       if (cfg->compile_aot) {
+                                               NEW_AOTCONST_TOKEN (cfg, iargs [1], MONO_PATCH_INFO_RVA, method->klass->image, GPOINTER_TO_UINT(data_ptr), STACK_PTR, NULL);
+                                       } else {
+                                               NEW_PCONST (cfg, iargs [1], data_ptr);
+                                       }
+                                       mono_emit_method_call_spilled (cfg, bblock, memcpy_method, memcpy_method->signature, iargs, ip, NULL);
+                                       ip += 11;
+                               }
                                NEW_TEMPLOAD (cfg, load, temp->inst_c0);
                                load->cil_code = ins->cil_code;
                                *sp++ = load;
@@ -6301,8 +6481,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                UNVERIFIED;
 
                        klass = mini_get_class (method, read32 (ip + 1), generic_context);
-                       if (!klass)
-                               goto load_error;                        
+                       CHECK_TYPELOAD (klass);
                        /* we need to make sure that this array is exactly the type it needs
                         * to be for correctness. the wrappers are lax with their usage
                         * so we need to ignore them here
@@ -6333,8 +6512,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
                        klass = mono_class_get_full (image, token, generic_context);
-                       if (!klass)
-                               goto load_error;
+                       CHECK_TYPELOAD (klass);
                        mono_class_init (klass);
                        NEW_LDELEMA (cfg, load, sp, klass);
                        load->cil_code = ip;
@@ -6370,6 +6548,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        klass = array_access_to_klass (*ip);
                        NEW_LDELEMA (cfg, load, sp, klass);
                        load->cil_code = ip;
+#ifdef MONO_ARCH_SOFT_FLOAT
+                       if (*ip == CEE_LDELEM_R4) {
+                               int temp;
+                               temp = handle_load_float (cfg, bblock, load, ip);
+                               NEW_TEMPLOAD (cfg, *sp, temp);
+                               sp++;
+                               ++ip;
+                               break;
+                       }
+#endif
                        MONO_INST_NEW (cfg, ins, ldelem_to_ldind [*ip - CEE_LDELEM_I1]);
                        ins->cil_code = ip;
                        ins->inst_left = load;
@@ -6399,6 +6587,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        klass = array_access_to_klass (*ip);
                        NEW_LDELEMA (cfg, load, sp, klass);
                        load->cil_code = ip;
+#ifdef MONO_ARCH_SOFT_FLOAT
+                       if (*ip == CEE_STELEM_R4) {
+                               handle_store_float (cfg, bblock, load, sp [2], ip);
+                               ip++;
+                               break;
+                       }
+#endif
                        MONO_INST_NEW (cfg, ins, stelem_to_stind [*ip - CEE_STELEM_I]);
                        ins->cil_code = ip;
                        ins->inst_left = load;
@@ -6423,8 +6618,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
                        klass = mono_class_get_full (image, token, generic_context);
-                       if (!klass)
-                               goto load_error;
+                       CHECK_TYPELOAD (klass);
                        mono_class_init (klass);
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                MonoMethod* helper = mono_marshal_get_stelemref ();
@@ -6519,8 +6713,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        --sp;
                        CHECK_OPSIZE (5);
                        klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
-                       if (!klass)
-                               goto load_error;
+                       CHECK_TYPELOAD (klass);
                        mono_class_init (klass);
                        ins->type = STACK_MP;
                        ins->inst_left = *sp;
@@ -6538,8 +6731,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        --sp;
                        CHECK_OPSIZE (5);
                        klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
-                       if (!klass)
-                               goto load_error;
+                       CHECK_TYPELOAD (klass);
                        mono_class_init (klass);
                        ins->cil_code = ip;
 
@@ -6716,8 +6908,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                }
                        }
 
-                       /* fixme: call fault handler ? */
-
                        if ((handlers = mono_find_final_block (cfg, ip, target, MONO_EXCEPTION_CLAUSE_FINALLY))) {
                                GList *tmp;
                                for (tmp = handlers; tmp; tmp = tmp->next) {
@@ -6779,7 +6969,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                token = read32 (ip + 2);
                                func = mono_method_get_wrapper_data (method, token);
                                info = mono_find_jit_icall_by_addr (func);
-                               g_assert (info);
+                               if (info == NULL){
+                                       g_error ("An attempt has been made to perform an icall to address %p, "
+                                                "but the address has not been registered as an icall\n", info);
+                                       g_assert_not_reached ();
+                               }
 
                                CHECK_STACK (info->sig->param_count);
                                sp -= info->sig->param_count;
@@ -6970,13 +7164,21 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                cmp->cil_code = ip;
                                type_from_op (cmp);
                                CHECK_TYPE (cmp);
+                               ins->cil_code = ip;
+                               ins->type = STACK_I4;
+                               ins->inst_i0 = cmp;
+#if MONO_ARCH_SOFT_FLOAT
+                               if (sp [0]->type == STACK_R8) {
+                                       cmp->type = STACK_I4;
+                                       *sp++ = emit_tree (cfg, bblock, cmp, ip + 2);
+                                       ip += 2;
+                                       break;
+                               }
+#endif
                                if ((sp [0]->type == STACK_I8) || ((sizeof (gpointer) == 8) && ((sp [0]->type == STACK_PTR) || (sp [0]->type == STACK_OBJ) || (sp [0]->type == STACK_MP))))
                                        cmp->opcode = OP_LCOMPARE;
                                else
                                        cmp->opcode = OP_COMPARE;
-                               ins->cil_code = ip;
-                               ins->type = STACK_I4;
-                               ins->inst_i0 = cmp;
                                *sp++ = ins;
                                /* spill it to reduce the expression complexity
                                 * and workaround bug 54209 
@@ -7055,6 +7257,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                n = read16 (ip + 2);
                                CHECK_ARG (n);
                                NEW_ARGLOAD (cfg, ins, n);
+                               LDARG_SOFT_FLOAT (cfg, ins, n, ip);
                                ins->cil_code = ip;
                                *sp++ = ins;
                                ip += 4;
@@ -7093,6 +7296,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                n = read16 (ip + 2);
                                CHECK_LOCAL (n);
                                NEW_LOCLOAD (cfg, ins, n);
+                               LDLOC_SOFT_FLOAT (cfg, ins, n, ip);
                                ins->cil_code = ip;
                                *sp++ = ins;
                                ip += 4;
@@ -7118,6 +7322,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (!dont_verify_stloc && target_type_is_incompatible (cfg, header->locals [n], *sp))
                                        UNVERIFIED;
                                ins->cil_code = ip;
+                               STLOC_SOFT_FLOAT (cfg, ins, n, ip);
                                if (ins->opcode == CEE_STOBJ) {
                                        NEW_LOCLOADA (cfg, ins, n);
                                        handle_stobj (cfg, bblock, ins, *sp, ip, ins->klass, FALSE, FALSE, FALSE);
@@ -7206,8 +7411,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_OPSIZE (6);
                                token = read32 (ip + 2);
                                klass = mini_get_class (method, token, generic_context);
-                               if (!klass)
-                                       goto load_error;
+                               CHECK_TYPELOAD (klass);
                                if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                        MonoInst *store, *load;
                                        NEW_PCONST (cfg, load, NULL);
@@ -7231,8 +7435,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_OPSIZE (6);
                                token = read32 (ip + 2);
                                constrained_call = mono_class_get_full (image, token, generic_context);
-                               if (!constrained_call)
-                                       goto load_error;
+                               CHECK_TYPELOAD (constrained_call);
                                ip += 6;
                                break;
                        case CEE_CPBLK:
@@ -7313,8 +7516,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        token = mono_type_size (type, &ialign);
                                } else {
                                        MonoClass *klass = mono_class_get_full (image, token, generic_context);
-                                       if (!klass)
-                                               goto load_error;
+                                       CHECK_TYPELOAD (klass);
                                        mono_class_init (klass);
                                        token = mono_class_value_size (klass, &align);
                                }
@@ -7396,11 +7598,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                NEW_LOCSTORE (cfg, store, i, ins);
                                MONO_ADD_INS (init_localsbb, store);
                        } else if (t == MONO_TYPE_R4 || t == MONO_TYPE_R8) {
+#ifdef MONO_ARCH_SOFT_FLOAT
+                               /* FIXME: handle init of R4 */
+#else
                                MONO_INST_NEW (cfg, ins, OP_R8CONST);
                                ins->type = STACK_R8;
                                ins->inst_p0 = (void*)&r8_0;
                                NEW_LOCSTORE (cfg, store, i, ins);
                                MONO_ADD_INS (init_localsbb, store);
+#endif
                        } else if ((t == MONO_TYPE_VALUETYPE) || (t == MONO_TYPE_TYPEDBYREF) ||
                                   ((t == MONO_TYPE_GENERICINST) && mono_type_generic_inst_is_valuetype (ptype))) {
                                NEW_LOCLOADA (cfg, ins, i);
@@ -8188,6 +8394,58 @@ decompose_foreach (MonoInst *tree, gpointer data)
                        dec_foreach (iargs [i], cfg);
                break;
        }
+#ifdef MONO_ARCH_SOFT_FLOAT
+       case OP_FBEQ:
+       case OP_FBGE:
+       case OP_FBGT:
+       case OP_FBLE:
+       case OP_FBLT:
+       case OP_FBNE_UN:
+       case OP_FBGE_UN:
+       case OP_FBGT_UN:
+       case OP_FBLE_UN:
+       case OP_FBLT_UN: {
+               if ((info = mono_find_jit_opcode_emulation (tree->opcode))) {
+                       MonoCompile *cfg = data;
+                       MonoInst *iargs [2];
+               
+                       iargs [0] = tree->inst_i0;
+                       iargs [1] = tree->inst_i1;
+               
+                       mono_emulate_opcode (cfg, tree, iargs, info);
+
+                       dec_foreach (iargs [0], cfg);
+                       dec_foreach (iargs [1], cfg);
+                       break;
+               } else {
+                       g_assert_not_reached ();
+               }
+               break;
+       }
+       case OP_FCEQ:
+       case OP_FCGT:
+       case OP_FCGT_UN:
+       case OP_FCLT:
+       case OP_FCLT_UN: {
+               if ((info = mono_find_jit_opcode_emulation (tree->opcode))) {
+                       MonoCompile *cfg = data;
+                       MonoInst *iargs [2];
+
+                       /* the args are in the compare opcode ... */
+                       iargs [0] = tree->inst_i0;
+                       iargs [1] = tree->inst_i1;
+               
+                       mono_emulate_opcode (cfg, tree, iargs, info);
+
+                       dec_foreach (iargs [0], cfg);
+                       dec_foreach (iargs [1], cfg);
+                       break;
+               } else {
+                       g_assert_not_reached ();
+               }
+               break;
+       }
+#endif
 
        default:
                break;
@@ -8550,6 +8808,7 @@ mono_patch_info_dup_mp (MonoMemPool *mp, MonoJumpInfo *patch_info)
        memcpy (res, patch_info, sizeof (MonoJumpInfo));
 
        switch (patch_info->type) {
+       case MONO_PATCH_INFO_RVA:
        case MONO_PATCH_INFO_LDSTR:
        case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
        case MONO_PATCH_INFO_LDTOKEN:
@@ -8574,6 +8833,7 @@ mono_patch_info_hash (gconstpointer data)
        const MonoJumpInfo *ji = (MonoJumpInfo*)data;
 
        switch (ji->type) {
+       case MONO_PATCH_INFO_RVA:
        case MONO_PATCH_INFO_LDSTR:
        case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
        case MONO_PATCH_INFO_LDTOKEN:
@@ -8601,6 +8861,7 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
                return 0;
 
        switch (ji1->type) {
+       case MONO_PATCH_INFO_RVA:
        case MONO_PATCH_INFO_LDSTR:
        case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
        case MONO_PATCH_INFO_LDTOKEN:
@@ -8718,6 +8979,9 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = (char*)vtable->data + patch_info->data.field->offset;
                break;
        }
+       case MONO_PATCH_INFO_RVA:
+               target = mono_image_rva_map (patch_info->data.token->image, patch_info->data.token->token);
+               break;
        case MONO_PATCH_INFO_R4:
        case MONO_PATCH_INFO_R8:
                target = patch_info->data.target;
@@ -9542,7 +9806,12 @@ emit_state (MonoCompile *cfg, MBState *state, int goal)
                state->reg2 = mono_regstate_next_int (cfg->rs);
                break;
        case MB_NTERM_freg:
+#ifdef MONO_ARCH_SOFT_FLOAT
+               state->reg1 = mono_regstate_next_int (cfg->rs);
+               state->reg2 = mono_regstate_next_int (cfg->rs);
+#else
                state->reg1 = mono_regstate_next_float (cfg->rs);
+#endif
                break;
        default:
 #ifdef MONO_ARCH_ENABLE_EMIT_STATE_OPT
@@ -10395,11 +10664,16 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                /* Throw a type load exception if needed */
                MonoLoaderError *error = mono_loader_get_last_error ();
 
-               mono_destroy_compile (cfg);
                if (error) {
                        MonoException *ex = mono_loader_error_prepare_exception (error);
+                       mono_destroy_compile (cfg);
                        mono_raise_exception (ex);
                } else {
+                       if (cfg->exception_ptr) {
+                               MonoException *ex = mono_class_get_exception_for_failure (cfg->exception_ptr);
+                               mono_destroy_compile (cfg);
+                               mono_raise_exception (ex);
+                       }
                        g_assert_not_reached ();
                }
        }
@@ -10663,25 +10937,33 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
        return runtime_invoke (obj, params, exc, compiled_method);
 }
 
+#ifdef MONO_GET_CONTEXT
+#define GET_CONTEXT MONO_GET_CONTEXT
+#endif
+
+#ifndef GET_CONTEXT
 #ifdef PLATFORM_WIN32
 #define GET_CONTEXT \
        struct sigcontext *ctx = (struct sigcontext*)_dummy;
 #else
-#ifdef __sparc
+#ifdef MONO_ARCH_USE_SIGACTION
 #define GET_CONTEXT \
     void *ctx = context;
-#elif defined (MONO_ARCH_USE_SIGACTION)
+#elif defined(__sparc__)
 #define GET_CONTEXT \
-    void *ctx = context;
+    void *ctx = sigctx;
 #else
 #define GET_CONTEXT \
        void **_p = (void **)&_dummy; \
        struct sigcontext *ctx = (struct sigcontext *)++_p;
 #endif
 #endif
+#endif
 
 #ifdef MONO_ARCH_USE_SIGACTION
 #define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *info, void *context)
+#elif defined(__sparc__)
+#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, void *sigctx)
 #else
 #define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy)
 #endif
@@ -11219,7 +11501,7 @@ mini_parse_debug_options (void)
 }
 
 MonoDomain *
-mini_init (const char *filename)
+mini_init (const char *filename, const char *runtime_version)
 {
        MonoDomain *domain;
 
@@ -11337,7 +11619,10 @@ mini_init (const char *filename)
                mono_aot_set_make_unreadable (TRUE);
        }
 
-       domain = mono_init_from_assembly (filename, filename);
+       if (runtime_version)
+               domain = mono_init_version (filename, runtime_version);
+       else
+               domain = mono_init_from_assembly (filename, filename);
        mono_icall_init ();
 
        mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info", 
@@ -11449,6 +11734,8 @@ mini_init (const char *filename)
        mono_register_opcode_emulation (OP_FADD, "__emul_fadd", "double double double", mono_fadd, FALSE);
        mono_register_opcode_emulation (OP_FMUL, "__emul_fmul", "double double double", mono_fmul, FALSE);
        mono_register_opcode_emulation (OP_FNEG, "__emul_fneg", "double double", mono_fneg, FALSE);
+       mono_register_opcode_emulation (CEE_CONV_R8, "__emul_conv_r8", "double int32", mono_conv_to_r8, FALSE);
+       mono_register_opcode_emulation (CEE_CONV_R4, "__emul_conv_r4", "double int32", mono_conv_to_r4, FALSE);
        mono_register_opcode_emulation (OP_FCONV_TO_R4, "__emul_fconv_to_r4", "double double", mono_fconv_r4, FALSE);
        mono_register_opcode_emulation (OP_FCONV_TO_I1, "__emul_fconv_to_i1", "int8 double", mono_fconv_i1, FALSE);
        mono_register_opcode_emulation (OP_FCONV_TO_I2, "__emul_fconv_to_i2", "int16 double", mono_fconv_i2, FALSE);
@@ -11466,6 +11753,16 @@ mini_init (const char *filename)
        mono_register_opcode_emulation (OP_FBGT_UN, "__emul_fcmp_gt_un", "uint32 double double", mono_fcmp_gt_un, FALSE);
        mono_register_opcode_emulation (OP_FBLE_UN, "__emul_fcmp_le_un", "uint32 double double", mono_fcmp_le_un, FALSE);
        mono_register_opcode_emulation (OP_FBGE_UN, "__emul_fcmp_ge_un", "uint32 double double", mono_fcmp_ge_un, FALSE);
+
+       mono_register_opcode_emulation (OP_FCEQ, "__emul_fcmp_ceq", "uint32 double double", mono_fceq, FALSE);
+       mono_register_opcode_emulation (OP_FCGT, "__emul_fcmp_cgt", "uint32 double double", mono_fcgt, FALSE);
+       mono_register_opcode_emulation (OP_FCGT_UN, "__emul_fcmp_cgt_un", "uint32 double double", mono_fcgt_un, FALSE);
+       mono_register_opcode_emulation (OP_FCLT, "__emul_fcmp_clt", "uint32 double double", mono_fclt, FALSE);
+       mono_register_opcode_emulation (OP_FCLT_UN, "__emul_fcmp_clt_un", "uint32 double double", mono_fclt_un, FALSE);
+
+       register_icall (mono_fload_r4, "mono_fload_r4", "double ptr", FALSE);
+       register_icall (mono_fstore_r4, "mono_fstore_r4", "void double ptr", FALSE);
+       register_icall (mono_fload_r4_arg, "mono_fload_r4_arg", "uint32 double", FALSE);
 #endif
 
 #if SIZEOF_VOID_P == 4