[llvm] Fix the decomposition of some long opcodes on 32 bit machines.
[mono.git] / mono / mini / decompose.c
1 /*
2  * decompose.c: Functions to decompose complex IR instructions into simpler ones.
3  *
4  * Author:
5  *   Zoltan Varga (vargaz@gmail.com)
6  *
7  * (C) 2002 Ximian, Inc.
8  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
9  */
10
11 #include "mini.h"
12 #include "ir-emit.h"
13 #include "jit-icalls.h"
14
15 #include <mono/metadata/gc-internal.h>
16
17 #ifndef DISABLE_JIT
18
19 /* FIXME: This conflicts with the definition in mini.c, so it cannot be moved to mini.h */
20 MONO_API MonoInst* mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature *sig, MonoInst **args);
21 void mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native);
22 void mini_emit_initobj (MonoCompile *cfg, MonoInst *dest, const guchar *ip, MonoClass *klass);
23
24 /*
25  * Decompose complex long opcodes on 64 bit machines.
26  * This is also used on 32 bit machines when using LLVM, so it needs to handle I/U correctly.
27  */
28 static gboolean
29 decompose_long_opcode (MonoCompile *cfg, MonoInst *ins, MonoInst **repl_ins)
30 {
31         MonoInst *repl = NULL;
32
33         *repl_ins = NULL;
34
35         switch (ins->opcode) {
36         case OP_LCONV_TO_I4:
37                 ins->opcode = OP_SEXT_I4;
38                 break;
39         case OP_LCONV_TO_I8:
40         case OP_LCONV_TO_U8:
41                 if (SIZEOF_VOID_P == 4)
42                         ins->opcode = OP_LMOVE;
43                 else
44                         ins->opcode = OP_MOVE;
45                 break;
46         case OP_LCONV_TO_I:
47                 if (SIZEOF_VOID_P == 4)
48                         /* OP_LCONV_TO_I4 */
49                         ins->opcode = OP_SEXT_I4;
50                 else
51                         ins->opcode = OP_MOVE;
52                 break;
53         case OP_LCONV_TO_U:
54                 if (SIZEOF_VOID_P == 4) {
55                         /* OP_LCONV_TO_U4 */
56                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, ins->dreg, ins->sreg1, 0);
57                         NULLIFY_INS (ins);
58                 } else {
59                         ins->opcode = OP_MOVE;
60                 }
61                 break;
62         case OP_ICONV_TO_I8:
63                 ins->opcode = OP_SEXT_I4;
64                 break;
65         case OP_ICONV_TO_U8:
66                 ins->opcode = OP_ZEXT_I4;
67                 break;
68         case OP_LCONV_TO_U4:
69                 /* Clean out the upper word */
70                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, ins->dreg, ins->sreg1, 0);
71                 NULLIFY_INS (ins);
72                 break;
73         case OP_LADD_OVF:
74                 if (COMPILE_LLVM (cfg))
75                         break;
76                 {
77                         int opcode;
78 #if defined(__mono_ilp32__) && SIZEOF_REGISTER == 8
79                         opcode = OP_LADDCC;
80 #else
81                         opcode = OP_ADDCC;
82 #endif
83                         EMIT_NEW_BIALU (cfg, repl, opcode, ins->dreg, ins->sreg1, ins->sreg2);
84                 }
85                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
86                 NULLIFY_INS (ins);
87                 break;
88         case OP_LADD_OVF_UN:
89                 if (COMPILE_LLVM (cfg))
90                         break;
91                 {
92                         int opcode;
93 #if defined(__mono_ilp32__) && SIZEOF_REGISTER == 8
94                         opcode = OP_LADDCC;
95 #else
96                         opcode = OP_ADDCC;
97 #endif
98                         EMIT_NEW_BIALU (cfg, repl, opcode, ins->dreg, ins->sreg1, ins->sreg2);
99                 }
100                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
101                 NULLIFY_INS (ins);
102                 break;
103 #ifndef __mono_ppc64__
104         case OP_LSUB_OVF:
105                 if (COMPILE_LLVM (cfg))
106                         break;
107                 {
108                         int opcode;
109 #if defined(__mono_ilp32__) && SIZEOF_REGISTER == 8
110                         opcode = OP_LSUBCC;
111 #else
112                         opcode = OP_SUBCC;
113 #endif
114                         EMIT_NEW_BIALU (cfg, repl, opcode, ins->dreg, ins->sreg1, ins->sreg2);
115                 }
116                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
117                 NULLIFY_INS (ins);
118                 break;
119         case OP_LSUB_OVF_UN:
120                 if (COMPILE_LLVM (cfg))
121                         break;
122                 {
123                         int opcode;
124 #if defined(__mono_ilp32__) && SIZEOF_REGISTER == 8
125                         opcode = OP_LSUBCC;
126 #else
127                         opcode = OP_SUBCC;
128 #endif
129                         EMIT_NEW_BIALU (cfg, repl, opcode, ins->dreg, ins->sreg1, ins->sreg2);
130                 }
131                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
132                 NULLIFY_INS (ins);
133                 break;
134 #endif
135                 
136         case OP_ICONV_TO_OVF_I8:
137         case OP_ICONV_TO_OVF_I:
138                 ins->opcode = OP_SEXT_I4;
139                 break;
140         case OP_ICONV_TO_OVF_U8:
141         case OP_ICONV_TO_OVF_U:
142                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg,ins->sreg1, 0);
143                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
144                 MONO_EMIT_NEW_UNALU (cfg, OP_ZEXT_I4, ins->dreg, ins->sreg1);
145                 NULLIFY_INS (ins);
146                 break;
147         case OP_ICONV_TO_OVF_I8_UN:
148         case OP_ICONV_TO_OVF_U8_UN:
149         case OP_ICONV_TO_OVF_I_UN:
150         case OP_ICONV_TO_OVF_U_UN:
151                 /* an unsigned 32 bit num always fits in an (un)signed 64 bit one */
152                 /* Clean out the upper word */
153                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, ins->dreg, ins->sreg1, 0);
154                 NULLIFY_INS (ins);
155                 break;
156         case OP_LCONV_TO_OVF_I1:
157                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 127);
158                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
159                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, -128);
160                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
161                 MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I1, ins->dreg, ins->sreg1);
162                 NULLIFY_INS (ins);
163                 break;
164         case OP_LCONV_TO_OVF_I1_UN:
165                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 127);
166                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
167                 MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I1, ins->dreg, ins->sreg1);
168                 NULLIFY_INS (ins);
169                 break;
170         case OP_LCONV_TO_OVF_U1:
171                 /* probe value to be within 0 to 255 */
172                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 255);
173                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
174                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xff);
175                 NULLIFY_INS (ins);
176                 break;
177         case OP_LCONV_TO_OVF_U1_UN:
178                 /* probe value to be within 0 to 255 */
179                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 255);
180                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
181                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xff);
182                 NULLIFY_INS (ins);
183                 break;
184         case OP_LCONV_TO_OVF_I2:
185                 /* Probe value to be within -32768 and 32767 */
186                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 32767);
187                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
188                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, -32768);
189                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
190                 MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I2, ins->dreg, ins->sreg1);
191                 NULLIFY_INS (ins);
192                 break;
193         case OP_LCONV_TO_OVF_I2_UN:
194                 /* Probe value to be within 0 and 32767 */
195                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 32767);
196                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
197                 MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I2, ins->dreg, ins->sreg1);
198                 NULLIFY_INS (ins);
199                 break;
200         case OP_LCONV_TO_OVF_U2:
201                 /* Probe value to be within 0 and 65535 */
202                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0xffff);
203                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
204                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xffff);
205                 NULLIFY_INS (ins);
206                 break;
207         case OP_LCONV_TO_OVF_U2_UN:
208                 /* Probe value to be within 0 and 65535 */
209                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0xffff);
210                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
211                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xffff);
212                 NULLIFY_INS (ins);
213                 break;
214         case OP_LCONV_TO_OVF_I4:
215 #if SIZEOF_VOID_P == 4
216         case OP_LCONV_TO_OVF_I:
217 #endif
218                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0x7fffffff);
219                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
220                 /* The int cast is needed for the VS compiler.  See Compiler Warning (level 2) C4146. */
221 #if SIZEOF_REGISTER == 8
222                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, ((int)-2147483648));
223 #else
224                 g_assert (COMPILE_LLVM (cfg));
225                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, -2147483648LL);
226 #endif
227                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
228                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
229                 NULLIFY_INS (ins);
230                 break;
231         case OP_LCONV_TO_OVF_I4_UN:
232 #if SIZEOF_VOID_P == 4
233         case OP_LCONV_TO_OVF_I_UN:
234 #endif
235                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0x7fffffff);
236                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
237                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
238                 NULLIFY_INS (ins);
239                 break;
240         case OP_LCONV_TO_OVF_U4:
241 #if SIZEOF_VOID_P == 4
242         case OP_LCONV_TO_OVF_U:
243 #endif
244                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0xffffffffUL);
245                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
246                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0);
247                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
248                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
249                 NULLIFY_INS (ins);
250                 break;
251         case OP_LCONV_TO_OVF_U4_UN:
252 #if SIZEOF_VOID_P == 4
253         case OP_LCONV_TO_OVF_U_UN:
254 #endif
255                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0xffffffff);
256                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
257                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
258                 NULLIFY_INS (ins);
259                 break;
260 #if SIZEOF_VOID_P == 8
261         case OP_LCONV_TO_OVF_I:
262         case OP_LCONV_TO_OVF_U_UN:
263 #endif
264         case OP_LCONV_TO_OVF_U8_UN:
265         case OP_LCONV_TO_OVF_I8:
266                 ins->opcode = OP_MOVE;
267                 break;
268 #if SIZEOF_VOID_P == 8
269         case OP_LCONV_TO_OVF_I_UN:
270 #endif
271         case OP_LCONV_TO_OVF_I8_UN:
272                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0);
273                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
274                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
275                 NULLIFY_INS (ins);
276                 break;
277         case OP_LCONV_TO_OVF_U8:
278 #if SIZEOF_VOID_P == 8
279         case OP_LCONV_TO_OVF_U:
280 #endif
281                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0);
282                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
283                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
284                 NULLIFY_INS (ins);
285                 break;
286         default:
287                 return FALSE;
288         }
289
290         *repl_ins = repl;
291         return TRUE;
292 }
293
294 /*
295  * mono_decompose_opcode:
296  *
297  *   Decompose complex opcodes into ones closer to opcodes supported by
298  * the given architecture.
299  * Returns a MonoInst which represents the result of the decomposition, and can
300  * be pushed on the IL stack. This is needed because the original instruction is
301  * nullified.
302  * Sets the cfg exception if an opcode is not supported.
303  */
304 MonoInst*
305 mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
306 {
307         MonoInst *repl = NULL;
308         int type = ins->type;
309         int dreg = ins->dreg;
310         gboolean emulate = FALSE;
311
312         /* FIXME: Instead of = NOP, don't emit the original ins at all */
313
314 #ifdef MONO_ARCH_HAVE_DECOMPOSE_OPTS
315         mono_arch_decompose_opts (cfg, ins);
316 #endif
317
318         /*
319          * The code below assumes that we are called immediately after emitting 
320          * ins. This means we can emit code using the normal code generation
321          * macros.
322          */
323         switch (ins->opcode) {
324         /* this doesn't make sense on ppc and other architectures */
325 #if !defined(MONO_ARCH_NO_IOV_CHECK)
326         case OP_IADD_OVF:
327                 if (COMPILE_LLVM (cfg))
328                         break;
329                 ins->opcode = OP_IADDCC;
330                 MONO_EMIT_NEW_COND_EXC (cfg, IOV, "OverflowException");
331                 break;
332         case OP_IADD_OVF_UN:
333                 if (COMPILE_LLVM (cfg))
334                         break;
335                 ins->opcode = OP_IADDCC;
336                 MONO_EMIT_NEW_COND_EXC (cfg, IC, "OverflowException");
337                 break;
338         case OP_ISUB_OVF:
339                 if (COMPILE_LLVM (cfg))
340                         break;
341                 ins->opcode = OP_ISUBCC;
342                 MONO_EMIT_NEW_COND_EXC (cfg, IOV, "OverflowException");
343                 break;
344         case OP_ISUB_OVF_UN:
345                 if (COMPILE_LLVM (cfg))
346                         break;
347                 ins->opcode = OP_ISUBCC;
348                 MONO_EMIT_NEW_COND_EXC (cfg, IC, "OverflowException");
349                 break;
350 #endif
351         case OP_ICONV_TO_OVF_I1:
352                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 127);
353                 MONO_EMIT_NEW_COND_EXC (cfg, IGT, "OverflowException");
354                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, -128);
355                 MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException");
356                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, ins->dreg, ins->sreg1);
357                 NULLIFY_INS (ins);
358                 break;
359         case OP_ICONV_TO_OVF_I1_UN:
360                 /* probe values between 0 to 127 */
361                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 127);
362                 MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException");
363                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, ins->dreg, ins->sreg1);
364                 NULLIFY_INS (ins);
365                 break;
366         case OP_ICONV_TO_OVF_U1:
367         case OP_ICONV_TO_OVF_U1_UN:
368                 /* probe value to be within 0 to 255 */
369                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 255);
370                 MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException");
371                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, ins->dreg, ins->sreg1, 0xff);
372                 NULLIFY_INS (ins);
373                 break;
374         case OP_ICONV_TO_OVF_I2:
375                 /* Probe value to be within -32768 and 32767 */
376                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 32767);
377                 MONO_EMIT_NEW_COND_EXC (cfg, IGT, "OverflowException");
378                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, -32768);
379                 MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException");
380                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, ins->dreg, ins->sreg1);
381                 NULLIFY_INS (ins);
382                 break;
383         case OP_ICONV_TO_OVF_I2_UN:
384                 /* Convert uint value into short, value within 0 and 32767 */
385                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 32767);
386                 MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException");
387                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, ins->dreg, ins->sreg1);
388                 NULLIFY_INS (ins);
389                 break;
390         case OP_ICONV_TO_OVF_U2:
391         case OP_ICONV_TO_OVF_U2_UN:
392                 /* Probe value to be within 0 and 65535 */
393                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0xffff);
394                 MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException");
395                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, ins->dreg, ins->sreg1, 0xffff);
396                 NULLIFY_INS (ins);
397                 break;
398         case OP_ICONV_TO_OVF_U4:
399         case OP_ICONV_TO_OVF_I4_UN:
400 #if SIZEOF_VOID_P == 4
401         case OP_ICONV_TO_OVF_U:
402         case OP_ICONV_TO_OVF_I_UN:
403 #endif
404                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0);
405                 MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException");
406                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
407                 NULLIFY_INS (ins);
408                 break;
409         case OP_ICONV_TO_I4:
410         case OP_ICONV_TO_U4:
411         case OP_ICONV_TO_OVF_I4:
412         case OP_ICONV_TO_OVF_U4_UN:
413 #if SIZEOF_VOID_P == 4
414         case OP_ICONV_TO_OVF_I:
415         case OP_ICONV_TO_OVF_U_UN:
416 #endif
417                 ins->opcode = OP_MOVE;
418                 break;
419         case OP_ICONV_TO_I:
420 #if SIZEOF_VOID_P == 8
421                 ins->opcode = OP_SEXT_I4;
422 #else
423                 ins->opcode = OP_MOVE;
424 #endif
425                 break;
426         case OP_ICONV_TO_U:
427 #if SIZEOF_VOID_P == 8
428                 ins->opcode = OP_ZEXT_I4;
429 #else
430                 ins->opcode = OP_MOVE;
431 #endif
432                 break;
433
434         case OP_FCONV_TO_R8:
435                 ins->opcode = OP_FMOVE;
436                 break;
437
438         case OP_FCONV_TO_OVF_I1_UN:
439         case OP_FCONV_TO_OVF_I2_UN:
440         case OP_FCONV_TO_OVF_I4_UN:
441         case OP_FCONV_TO_OVF_I8_UN:
442         case OP_FCONV_TO_OVF_U1_UN:
443         case OP_FCONV_TO_OVF_U2_UN:
444         case OP_FCONV_TO_OVF_U4_UN:
445         case OP_FCONV_TO_OVF_U8_UN:
446         case OP_FCONV_TO_OVF_I_UN:
447         case OP_FCONV_TO_OVF_U_UN:
448                 cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
449                 cfg->exception_message = g_strdup_printf ("float conv.ovf.un opcodes not supported.");
450                 break;
451
452 #if defined(MONO_ARCH_EMULATE_DIV) && defined(MONO_ARCH_HAVE_OPCODE_NEEDS_EMULATION)
453         case OP_IDIV:
454         case OP_IREM:
455         case OP_IDIV_UN:
456         case OP_IREM_UN:
457                 if (!mono_arch_opcode_needs_emulation (cfg, ins->opcode)) {
458 #ifdef MONO_ARCH_NEED_DIV_CHECK
459                         int reg1 = alloc_ireg (cfg);
460                         int reg2 = alloc_ireg (cfg);
461                         /* b == 0 */
462                         MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg2, 0);
463                         MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "DivideByZeroException");
464                         if (ins->opcode == OP_IDIV || ins->opcode == OP_IREM) {
465                                 /* b == -1 && a == 0x80000000 */
466                                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg2, -1);
467                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, reg1, -1);
468                                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0x80000000);
469                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, reg2, -1);
470                                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, reg1, reg1, reg2);
471                                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, reg1, 1);
472                                 MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "DivideByZeroException");
473                         }
474 #endif
475                         MONO_EMIT_NEW_BIALU (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->sreg2);
476                         ins->opcode = OP_NOP;
477                 } else {
478                         emulate = TRUE;
479                 }
480                 break;
481 #endif
482
483         default:
484                 emulate = TRUE;
485                 break;
486         }
487
488         if (emulate) {
489                 MonoJitICallInfo *info = NULL;
490
491 #if SIZEOF_REGISTER == 8
492                 if (decompose_long_opcode (cfg, ins, &repl))
493                         emulate = FALSE;
494 #else
495                 if (COMPILE_LLVM (cfg) && decompose_long_opcode (cfg, ins, &repl))
496                         emulate = FALSE;
497 #endif
498
499                 if (emulate)
500                         info = mono_find_jit_opcode_emulation (ins->opcode);
501                 if (info) {
502                         MonoInst **args;
503                         MonoInst *call;
504
505                         /* Create dummy MonoInst's for the arguments */
506                         g_assert (!info->sig->hasthis);
507                         g_assert (info->sig->param_count <= MONO_MAX_SRC_REGS);
508
509                         args = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * info->sig->param_count);
510                         if (info->sig->param_count > 0) {
511                                 int sregs [MONO_MAX_SRC_REGS];
512                                 int num_sregs, i;
513                                 num_sregs = mono_inst_get_src_registers (ins, sregs);
514                                 g_assert (num_sregs == info->sig->param_count);
515                                 for (i = 0; i < num_sregs; ++i) {
516                                         MONO_INST_NEW (cfg, args [i], OP_ARG);
517                                         args [i]->dreg = sregs [i];
518                                 }
519                         }
520
521                         call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, args);
522                         call->dreg = ins->dreg;
523
524                         NULLIFY_INS (ins);
525                 }
526         }
527
528         if (ins->opcode == OP_NOP) {
529                 if (repl) {
530                         repl->type = type;
531                         return repl;
532                 } else {
533                         /* Use the last emitted instruction */
534                         ins = cfg->cbb->last_ins;
535                         g_assert (ins);
536                         ins->type = type;
537                         g_assert (ins->dreg == dreg);
538                         return ins;
539                 }
540         } else {
541                 return ins;
542         }
543 }
544
545 #if SIZEOF_REGISTER == 4
546 static int lbr_decomp [][2] = {
547         {0, 0}, /* BEQ */
548         {OP_IBGT, OP_IBGE_UN}, /* BGE */
549         {OP_IBGT, OP_IBGT_UN}, /* BGT */
550         {OP_IBLT, OP_IBLE_UN}, /* BLE */
551         {OP_IBLT, OP_IBLT_UN}, /* BLT */
552         {0, 0}, /* BNE_UN */
553         {OP_IBGT_UN, OP_IBGE_UN}, /* BGE_UN */
554         {OP_IBGT_UN, OP_IBGT_UN}, /* BGT_UN */
555         {OP_IBLT_UN, OP_IBLE_UN}, /* BLE_UN */
556         {OP_IBLT_UN, OP_IBLT_UN}, /* BLT_UN */
557 };
558
559 static int lcset_decomp [][2] = {
560         {0, 0}, /* CEQ */
561         {OP_IBLT, OP_IBLE_UN}, /* CGT */
562         {OP_IBLT_UN, OP_IBLE_UN}, /* CGT_UN */
563         {OP_IBGT, OP_IBGE_UN}, /* CLT */
564         {OP_IBGT_UN, OP_IBGE_UN}, /* CLT_UN */
565 };
566 #endif
567
568 /**
569  * mono_decompose_long_opts:
570  *
571  *  Decompose 64bit opcodes into 32bit opcodes on 32 bit platforms.
572  */
573 void
574 mono_decompose_long_opts (MonoCompile *cfg)
575 {
576 #if SIZEOF_REGISTER == 4
577         MonoBasicBlock *bb, *first_bb;
578
579         /*
580          * Some opcodes, like lcall can't be decomposed so the rest of the JIT
581          * needs to be able to handle long vregs.
582          */
583
584         /* reg + 1 contains the ls word, reg + 2 contains the ms word */
585
586         /**
587          * Create a dummy bblock and emit code into it so we can use the normal 
588          * code generation macros.
589          */
590         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
591         first_bb = cfg->cbb;
592
593         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
594                 MonoInst *tree = bb->code;      
595                 MonoInst *prev = NULL;
596
597                    /*
598                 mono_print_bb (bb, "BEFORE LOWER_LONG_OPTS");
599                 */
600
601                 tree = bb->code;
602                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
603
604                 while (tree) {
605
606 #ifdef MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS
607                         mono_arch_decompose_long_opts (cfg, tree);
608 #endif
609
610                         switch (tree->opcode) {
611                         case OP_I8CONST:
612                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 1, tree->inst_ls_word);
613                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, tree->inst_ms_word);
614                                 break;
615                         case OP_DUMMY_I8CONST:
616                                 MONO_EMIT_NEW_DUMMY_INIT (cfg, tree->dreg + 1, OP_DUMMY_ICONST);
617                                 MONO_EMIT_NEW_DUMMY_INIT (cfg, tree->dreg + 2, OP_DUMMY_ICONST);
618                                 break;
619                         case OP_LMOVE:
620                         case OP_LCONV_TO_U8:
621                         case OP_LCONV_TO_I8:
622                         case OP_LCONV_TO_OVF_U8_UN:
623                         case OP_LCONV_TO_OVF_I8:
624                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1);
625                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2);
626                                 break;
627                         case OP_STOREI8_MEMBASE_REG:
628                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_MS_WORD_OFFSET, tree->sreg1 + 2);
629                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_LS_WORD_OFFSET, tree->sreg1 + 1);
630                                 break;
631                         case OP_LOADI8_MEMBASE:
632                                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tree->dreg + 2, tree->inst_basereg, tree->inst_offset + MINI_MS_WORD_OFFSET);
633                                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tree->dreg + 1, tree->inst_basereg, tree->inst_offset + MINI_LS_WORD_OFFSET);
634                                 break;
635
636                         case OP_ICONV_TO_I8: {
637                                 guint32 tmpreg = alloc_ireg (cfg);
638
639                                 /* branchless code:
640                                  * low = reg;
641                                  * tmp = low > -1 ? 1: 0;
642                                  * high = tmp - 1; if low is zero or pos high becomes 0, else -1
643                                  */
644                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
645                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, tree->dreg + 1, -1);
646                                 MONO_EMIT_NEW_BIALU (cfg, OP_ICGT, tmpreg, -1, -1);
647                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISUB_IMM, tree->dreg + 2, tmpreg, 1);
648                                 break;
649                         }
650                         case OP_ICONV_TO_U8:
651                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
652                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
653                                 break;
654                         case OP_ICONV_TO_OVF_I8:
655                                 /* a signed 32 bit num always fits in a signed 64 bit one */
656                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, tree->dreg + 2, tree->sreg1, 31);
657                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
658                                 break;
659                         case OP_ICONV_TO_OVF_U8:
660                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1, 0);
661                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
662                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
663                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
664                                 break;
665                         case OP_ICONV_TO_OVF_I8_UN:
666                         case OP_ICONV_TO_OVF_U8_UN:
667                                 /* an unsigned 32 bit num always fits in an (un)signed 64 bit one */
668                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
669                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
670                                 break;
671                         case OP_LCONV_TO_I1:
672                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1);
673                                 break;
674                         case OP_LCONV_TO_U1:
675                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U1, tree->dreg, tree->sreg1 + 1);
676                                 break;
677                         case OP_LCONV_TO_I2:
678                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1);
679                                 break;
680                         case OP_LCONV_TO_U2:
681                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U2, tree->dreg, tree->sreg1 + 1);
682                                 break;
683                         case OP_LCONV_TO_I4:
684                         case OP_LCONV_TO_U4:
685                         case OP_LCONV_TO_I:
686                         case OP_LCONV_TO_U:
687                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1);
688                                 break;
689                         case OP_LCONV_TO_R8:
690                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R8_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
691                                 break;
692                         case OP_LCONV_TO_R4:
693                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R4_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
694                                 break;
695                         case OP_LCONV_TO_R_UN:
696                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R_UN_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
697                                 break;
698                         case OP_LCONV_TO_OVF_I1: {
699                                 MonoBasicBlock *is_negative, *end_label;
700
701                                 NEW_BBLOCK (cfg, is_negative);
702                                 NEW_BBLOCK (cfg, end_label);
703
704                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
705                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
706                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, -1);
707                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
708
709                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
710                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative);
711
712                                 /* Positive */
713                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 127);
714                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
715                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label);
716
717                                 /* Negative */
718                                 MONO_START_BB (cfg, is_negative);
719                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -128);
720                                 MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException");
721
722                                 MONO_START_BB (cfg, end_label);
723
724                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1);
725                                 break;
726                         }
727                         case OP_LCONV_TO_OVF_I1_UN:
728                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
729                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
730
731                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 127);
732                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
733                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -128);
734                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
735                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1);
736                                 break;
737                         case OP_LCONV_TO_OVF_U1:
738                         case OP_LCONV_TO_OVF_U1_UN:
739                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
740                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
741
742                                 /* probe value to be within 0 to 255 */
743                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 255);
744                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
745                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, tree->sreg1 + 1, 0xff);
746                                 break;
747                         case OP_LCONV_TO_OVF_I2: {
748                                 MonoBasicBlock *is_negative, *end_label;
749
750                                 NEW_BBLOCK (cfg, is_negative);
751                                 NEW_BBLOCK (cfg, end_label);
752
753                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
754                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
755                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, -1);
756                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
757
758                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
759                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative);
760
761                                 /* Positive */
762                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 32767);
763                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
764                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label);
765
766                                 /* Negative */
767                                 MONO_START_BB (cfg, is_negative);
768                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -32768);
769                                 MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException");
770                                 MONO_START_BB (cfg, end_label);
771
772                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1);
773                                 break;
774                         }
775                         case OP_LCONV_TO_OVF_I2_UN:
776                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
777                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
778
779                                 /* Probe value to be within -32768 and 32767 */
780                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 32767);
781                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
782                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -32768);
783                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
784                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1);
785                                 break;
786                         case OP_LCONV_TO_OVF_U2:
787                         case OP_LCONV_TO_OVF_U2_UN:
788                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
789                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
790
791                                 /* Probe value to be within 0 and 65535 */
792                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 0xffff);
793                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
794                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, tree->sreg1 + 1, 0xffff);
795                                 break;
796                         case OP_LCONV_TO_OVF_I4:
797                         case OP_LCONV_TO_OVF_I:
798                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_OVF_I4_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
799                                 break;
800                         case OP_LCONV_TO_OVF_U4:
801                         case OP_LCONV_TO_OVF_U:
802                         case OP_LCONV_TO_OVF_U4_UN:
803                         case OP_LCONV_TO_OVF_U_UN:
804                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
805                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
806                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1);
807                                 break;
808                         case OP_LCONV_TO_OVF_I_UN:
809                         case OP_LCONV_TO_OVF_I4_UN:
810                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
811                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
812                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 1, 0);
813                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
814                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1);
815                                 break;
816                         case OP_LCONV_TO_OVF_U8:
817                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
818                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
819
820                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1);
821                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2);
822                                 break;
823                         case OP_LCONV_TO_OVF_I8_UN:
824                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
825                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
826
827                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1);
828                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2);
829                                 break;
830
831                         case OP_LADD:
832                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
833                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
834                                 break;
835                         case OP_LSUB:
836                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
837                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
838                                 break;
839
840                         case OP_LADD_OVF:
841                                 /* ADC sets the condition code */
842                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
843                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
844                                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
845                                 break;
846                         case OP_LADD_OVF_UN:
847                                 /* ADC sets the condition code */
848                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
849                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
850                                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
851                                 break;
852                         case OP_LSUB_OVF:
853                                 /* SBB sets the condition code */
854                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
855                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
856                                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
857                                 break;
858                         case OP_LSUB_OVF_UN:
859                                 /* SBB sets the condition code */
860                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
861                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
862                                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
863                                 break;
864                         case OP_LAND:
865                                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
866                                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
867                                 break;
868                         case OP_LOR:
869                                 MONO_EMIT_NEW_BIALU (cfg, OP_IOR, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
870                                 MONO_EMIT_NEW_BIALU (cfg, OP_IOR, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
871                                 break;
872                         case OP_LXOR:
873                                 MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
874                                 MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
875                                 break;
876                         case OP_LNOT:
877                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 1, tree->sreg1 + 1);
878                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 2, tree->sreg1 + 2);
879                                 break;
880                         case OP_LNEG:
881                                 /* Handled in mono_arch_decompose_long_opts () */
882                                 g_assert_not_reached ();
883                                 break;
884                         case OP_LMUL:
885                                 /* Emulated */
886                                 /* FIXME: Add OP_BIGMUL optimization */
887                                 break;
888
889                         case OP_LADD_IMM:
890                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADDCC_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
891                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
892                                 break;
893                         case OP_LSUB_IMM:
894                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUBCC_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
895                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SBB_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
896                                 break;
897                         case OP_LAND_IMM:
898                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
899                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
900                                 break;
901                         case OP_LOR_IMM:
902                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
903                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
904                                 break;
905                         case OP_LXOR_IMM:
906                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
907                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
908                                 break;
909                         case OP_LSHR_UN_IMM:
910                                 if (tree->inst_c1 == 32) {
911
912                                         /* The original code had this comment: */
913                                         /* special case that gives a nice speedup and happens to workaorund a ppc jit but (for the release)
914                                          * later apply the speedup to the left shift as well
915                                          * See BUG# 57957.
916                                          */
917                                         /* FIXME: Move this to the strength reduction pass */
918                                         /* just move the upper half to the lower and zero the high word */
919                                         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 2);
920                                         MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
921                                 }
922                                 break;
923                         case OP_LSHL_IMM:
924                                 if (tree->inst_c1 == 32) {
925                                         /* just move the lower half to the upper and zero the lower word */
926                                         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 1);
927                                         MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 1, 0);
928                                 }
929                                 break;
930
931                         case OP_LCOMPARE: {
932                                 MonoInst *next = tree->next;
933
934                                 g_assert (next);
935
936                                 switch (next->opcode) {
937                                 case OP_LBEQ:
938                                 case OP_LBNE_UN: {
939                                         int d1, d2;
940
941                                         /* Branchless version based on gcc code */
942                                         d1 = alloc_ireg (cfg);
943                                         d2 = alloc_ireg (cfg);
944                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, tree->sreg1 + 1, tree->sreg2 + 1);
945                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, tree->sreg1 + 2, tree->sreg2 + 2);
946                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
947                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
948                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
949                                         next->opcode = OP_NOP;
950                                         break;
951                                 }
952                                 case OP_LBGE:
953                                 case OP_LBGT:
954                                 case OP_LBLE:
955                                 case OP_LBLT:
956                                 case OP_LBGE_UN:
957                                 case OP_LBGT_UN:
958                                 case OP_LBLE_UN:
959                                 case OP_LBLT_UN:
960                                         /* Convert into three comparisons + branches */
961                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
962                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lbr_decomp [next->opcode - OP_LBEQ][0], next->inst_true_bb);
963                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
964                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
965                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1);
966                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
967                                         next->opcode = OP_NOP;
968                                         break;
969                                 case OP_LCEQ: {
970                                         int d1, d2;
971         
972                                         /* Branchless version based on gcc code */
973                                         d1 = alloc_ireg (cfg);
974                                         d2 = alloc_ireg (cfg);
975                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, tree->sreg1 + 1, tree->sreg2 + 1);
976                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, tree->sreg1 + 2, tree->sreg2 + 2);
977                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
978
979                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
980                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
981                                         next->opcode = OP_NOP;
982                                         break;
983                                 }
984                                 case OP_LCLT:
985                                 case OP_LCLT_UN:
986                                 case OP_LCGT:
987                                 case OP_LCGT_UN: {
988                                         MonoBasicBlock *set_to_0, *set_to_1;
989         
990                                         NEW_BBLOCK (cfg, set_to_0);
991                                         NEW_BBLOCK (cfg, set_to_1);
992
993                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 0);
994                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
995                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][0], set_to_0);
996                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
997                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, set_to_1);
998                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1);
999                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][1], set_to_0);
1000                                         MONO_START_BB (cfg, set_to_1);
1001                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
1002                                         MONO_START_BB (cfg, set_to_0);
1003                                         next->opcode = OP_NOP;
1004                                         break;  
1005                                 }
1006                                 default:
1007                                         g_assert_not_reached ();
1008                                 }
1009                                 break;
1010                         }
1011
1012                         /* Not yet used, since lcompare is decomposed before local cprop */
1013                         case OP_LCOMPARE_IMM: {
1014                                 MonoInst *next = tree->next;
1015                                 guint32 low_imm = tree->inst_ls_word;
1016                                 guint32 high_imm = tree->inst_ms_word;
1017                                 int low_reg = tree->sreg1 + 1;
1018                                 int high_reg = tree->sreg1 + 2;
1019
1020                                 g_assert (next);
1021
1022                                 switch (next->opcode) {
1023                                 case OP_LBEQ:
1024                                 case OP_LBNE_UN: {
1025                                         int d1, d2;
1026
1027                                         /* Branchless version based on gcc code */
1028                                         d1 = alloc_ireg (cfg);
1029                                         d2 = alloc_ireg (cfg);
1030                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d1, low_reg, low_imm);
1031                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d2, high_reg, high_imm);
1032                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
1033                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
1034                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
1035                                         next->opcode = OP_NOP;
1036                                         break;
1037                                 }
1038
1039                                 case OP_LBGE:
1040                                 case OP_LBGT:
1041                                 case OP_LBLE:
1042                                 case OP_LBLT:
1043                                 case OP_LBGE_UN:
1044                                 case OP_LBGT_UN:
1045                                 case OP_LBLE_UN:
1046                                 case OP_LBLT_UN:
1047                                         /* Convert into three comparisons + branches */
1048                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1049                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lbr_decomp [next->opcode - OP_LBEQ][0], next->inst_true_bb);
1050                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1051                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
1052                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
1053                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
1054                                         next->opcode = OP_NOP;
1055                                         break;
1056                                 case OP_LCEQ: {
1057                                         int d1, d2;
1058         
1059                                         /* Branchless version based on gcc code */
1060                                         d1 = alloc_ireg (cfg);
1061                                         d2 = alloc_ireg (cfg);
1062                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d1, low_reg, low_imm);
1063                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d2, high_reg, high_imm);
1064                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
1065
1066                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
1067                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
1068                                         next->opcode = OP_NOP;
1069                                         break;
1070                                 }
1071                                 case OP_LCLT:
1072                                 case OP_LCLT_UN:
1073                                 case OP_LCGT:
1074                                 case OP_LCGT_UN: {
1075                                         MonoBasicBlock *set_to_0, *set_to_1;
1076         
1077                                         NEW_BBLOCK (cfg, set_to_0);
1078                                         NEW_BBLOCK (cfg, set_to_1);
1079
1080                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 0);
1081                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1082                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][0], set_to_0);
1083                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1084                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, set_to_1);
1085                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
1086                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][1], set_to_0);
1087                                         MONO_START_BB (cfg, set_to_1);
1088                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
1089                                         MONO_START_BB (cfg, set_to_0);
1090                                         next->opcode = OP_NOP;
1091                                         break;  
1092                                 }
1093                                 default:
1094                                         g_assert_not_reached ();
1095                                 }
1096                                 break;
1097                         }
1098
1099                         default:
1100                                 break;
1101                         }
1102
1103                         if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1104                                 MonoInst *new_prev;
1105
1106                                 /* Replace the original instruction with the new code sequence */
1107
1108                                 /* Ignore the new value of prev */
1109                                 new_prev = prev;
1110                                 mono_replace_ins (cfg, bb, tree, &new_prev, first_bb, cfg->cbb);
1111
1112                                 /* Process the newly added ops again since they can be long ops too */
1113                                 if (prev)
1114                                         tree = prev->next;
1115                                 else
1116                                         tree = bb->code;
1117
1118                                 first_bb->code = first_bb->last_ins = NULL;
1119                                 first_bb->in_count = first_bb->out_count = 0;
1120                                 cfg->cbb = first_bb;
1121                         }
1122                         else {
1123                                 prev = tree;
1124                                 tree = tree->next;
1125                         }
1126                 }
1127         }
1128 #endif
1129
1130         /*
1131         for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
1132                 mono_print_bb (bb, "AFTER LOWER-LONG-OPTS");
1133         */
1134 }
1135
1136 /**
1137  * mono_decompose_vtype_opts:
1138  *
1139  *  Decompose valuetype opcodes.
1140  */
1141 void
1142 mono_decompose_vtype_opts (MonoCompile *cfg)
1143 {
1144         MonoBasicBlock *bb, *first_bb;
1145
1146         /**
1147          * Using OP_V opcodes and decomposing them later have two main benefits:
1148          * - it simplifies method_to_ir () since there is no need to special-case vtypes
1149          *   everywhere.
1150          * - it gets rid of the LDADDR opcodes generated when vtype operations are decomposed,
1151          *   enabling optimizations to work on vtypes too.
1152          * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it 
1153          * can be executed anytime. It should be executed as late as possible so vtype
1154          * opcodes can be optimized by the other passes.
1155          * The pinvoke wrappers need to manipulate vtypes in their unmanaged representation.
1156          * This is indicated by setting the 'backend.is_pinvoke' field of the MonoInst for the 
1157          * var to 1.
1158          * This is done on demand, ie. by the LDNATIVEOBJ opcode, and propagated by this pass 
1159          * when OP_VMOVE opcodes are decomposed.
1160          */
1161
1162         /* 
1163          * Vregs have no associated type information, so we store the type of the vregs
1164          * in ins->klass.
1165          */
1166
1167         /**
1168          * Create a dummy bblock and emit code into it so we can use the normal 
1169          * code generation macros.
1170          */
1171         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1172         first_bb = cfg->cbb;
1173
1174         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1175                 MonoInst *ins;
1176                 MonoInst *prev = NULL;
1177                 MonoInst *src_var, *dest_var, *src, *dest;
1178                 gboolean restart;
1179                 int dreg;
1180
1181                 if (cfg->verbose_level > 2) mono_print_bb (bb, "BEFORE LOWER-VTYPE-OPTS ");
1182
1183                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1184                 restart = TRUE;
1185
1186                 while (restart) {
1187                         restart = FALSE;
1188
1189                         for (ins = bb->code; ins; ins = ins->next) {
1190                                 switch (ins->opcode) {
1191                                 case OP_VMOVE: {
1192                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1193                                         dest_var = get_vreg_to_inst (cfg, ins->dreg);
1194
1195                                         g_assert (ins->klass);
1196
1197                                         if (!src_var)
1198                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1199
1200                                         if (!dest_var)
1201                                                 dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1202
1203                                         // FIXME:
1204                                         if (src_var->backend.is_pinvoke)
1205                                                 dest_var->backend.is_pinvoke = 1;
1206
1207                                         EMIT_NEW_VARLOADA ((cfg), (src), src_var, src_var->inst_vtype);
1208                                         EMIT_NEW_VARLOADA ((cfg), (dest), dest_var, dest_var->inst_vtype);
1209
1210                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1211                                         break;
1212                                 }
1213                                 case OP_VZERO:
1214                                         g_assert (ins->klass);
1215
1216                                         EMIT_NEW_VARLOADA_VREG (cfg, dest, ins->dreg, &ins->klass->byval_arg);
1217                                         mini_emit_initobj (cfg, dest, NULL, ins->klass);
1218                                         
1219                                         if (cfg->compute_gc_maps) {
1220                                                 MonoInst *tmp;
1221
1222                                                 /* 
1223                                                  * Tell the GC map code that the vtype is considered live after
1224                                                  * the initialization.
1225                                                  */
1226                                                 MONO_INST_NEW (cfg, tmp, OP_GC_LIVENESS_DEF);
1227                                                 tmp->inst_c1 = ins->dreg;
1228                                                 MONO_ADD_INS (cfg->cbb, tmp);
1229                                         }
1230                                         break;
1231                                 case OP_DUMMY_VZERO:
1232                                         NULLIFY_INS (ins);
1233                                         break;
1234                                 case OP_STOREV_MEMBASE: {
1235                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1236
1237                                         if (!src_var) {
1238                                                 g_assert (ins->klass);
1239                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1240                                         }
1241
1242                                         EMIT_NEW_VARLOADA_VREG ((cfg), (src), ins->sreg1, &ins->klass->byval_arg);
1243
1244                                         dreg = alloc_preg (cfg);
1245                                         EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
1246                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1247                                         break;
1248                                 }
1249                                 case OP_LOADV_MEMBASE: {
1250                                         g_assert (ins->klass);
1251
1252                                         dest_var = get_vreg_to_inst (cfg, ins->dreg);
1253                                         // FIXME-VT:
1254                                         // FIXME:
1255                                         if (!dest_var)
1256                                                 dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1257
1258                                         dreg = alloc_preg (cfg);
1259                                         EMIT_NEW_BIALU_IMM (cfg, src, OP_ADD_IMM, dreg, ins->inst_basereg, ins->inst_offset);
1260                                         EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
1261                                         mini_emit_stobj (cfg, dest, src, dest_var->klass, dest_var->backend.is_pinvoke);
1262                                         break;
1263                                 }
1264                                 case OP_OUTARG_VT: {
1265                                         g_assert (ins->klass);
1266
1267                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1268                                         if (!src_var)
1269                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1270                                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
1271
1272                                         mono_arch_emit_outarg_vt (cfg, ins, src);
1273
1274                                         /* This might be decomposed into other vtype opcodes */
1275                                         restart = TRUE;
1276                                         break;
1277                                 }
1278                                 case OP_OUTARG_VTRETADDR: {
1279                                         MonoCallInst *call = (MonoCallInst*)ins->inst_p1;
1280
1281                                         src_var = get_vreg_to_inst (cfg, call->inst.dreg);
1282                                         if (!src_var)
1283                                                 src_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
1284                                         // FIXME: src_var->backend.is_pinvoke ?
1285
1286                                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
1287                                         src->dreg = ins->dreg;
1288                                         break;
1289                                 }
1290                                 case OP_VCALL:
1291                                 case OP_VCALL_REG:
1292                                 case OP_VCALL_MEMBASE: {
1293                                         MonoCallInst *call = (MonoCallInst*)ins;
1294                                         int size;
1295
1296                                         if (call->vret_in_reg) {
1297                                                 MonoCallInst *call2;
1298
1299                                                 /* Replace the vcall with an integer call */
1300                                                 MONO_INST_NEW_CALL (cfg, call2, OP_NOP);
1301                                                 memcpy (call2, call, sizeof (MonoCallInst));
1302                                                 switch (ins->opcode) {
1303                                                 case OP_VCALL:
1304                                                         call2->inst.opcode = OP_CALL;
1305                                                         break;
1306                                                 case OP_VCALL_REG:
1307                                                         call2->inst.opcode = OP_CALL_REG;
1308                                                         break;
1309                                                 case OP_VCALL_MEMBASE:
1310                                                         call2->inst.opcode = OP_CALL_MEMBASE;
1311                                                         break;
1312                                                 }
1313                                                 call2->inst.dreg = alloc_preg (cfg);
1314                                                 MONO_ADD_INS (cfg->cbb, ((MonoInst*)call2));
1315
1316                                                 /* Compute the vtype location */
1317                                                 dest_var = get_vreg_to_inst (cfg, call->inst.dreg);
1318                                                 if (!dest_var)
1319                                                         dest_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
1320                                                 EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
1321
1322                                                 /* Save the result */
1323                                                 if (dest_var->backend.is_pinvoke)
1324                                                         size = mono_class_native_size (mono_class_from_mono_type (dest_var->inst_vtype), NULL);
1325                                                 else
1326                                                         size = mono_type_size (dest_var->inst_vtype, NULL);
1327                                                 switch (size) {
1328                                                 case 1:
1329                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1330                                                         break;
1331                                                 case 2:
1332                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1333                                                         break;
1334                                                 case 3:
1335                                                 case 4:
1336                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1337                                                         break;
1338                                                 case 5:
1339                                                 case 6:
1340                                                 case 7:
1341                                                 case 8:
1342 #if SIZEOF_REGISTER == 4
1343                                                         /*
1344                                                         FIXME Other ABIs might return in different regs than the ones used for LCALL.
1345                                                         FIXME It would be even nicer to be able to leverage the long decompose stuff.
1346                                                         */
1347                                                         switch (call2->inst.opcode) {
1348                                                         case OP_CALL:
1349                                                                 call2->inst.opcode = OP_LCALL;
1350                                                                 break;
1351                                                         case OP_CALL_REG:
1352                                                                 call2->inst.opcode = OP_LCALL_REG;
1353                                                                 break;
1354                                                         case OP_CALL_MEMBASE:
1355                                                                 call2->inst.opcode = OP_LCALL_MEMBASE;
1356                                                                 break;
1357                                                         }
1358                                                         call2->inst.dreg = alloc_lreg (cfg);
1359                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_MS_WORD_OFFSET, call2->inst.dreg + 2);
1360                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_LS_WORD_OFFSET, call2->inst.dreg + 1);
1361 #else
1362                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1363 #endif
1364                                                         break;
1365                                                 default:
1366                                                         /* This assumes the vtype is sizeof (gpointer) long */
1367                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1368                                                         break;
1369                                                 }
1370                                         } else {
1371                                                 switch (ins->opcode) {
1372                                                 case OP_VCALL:
1373                                                         ins->opcode = OP_VCALL2;
1374                                                         break;
1375                                                 case OP_VCALL_REG:
1376                                                         ins->opcode = OP_VCALL2_REG;
1377                                                         break;
1378                                                 case OP_VCALL_MEMBASE:
1379                                                         ins->opcode = OP_VCALL2_MEMBASE;
1380                                                         break;
1381                                                 }
1382                                                 ins->dreg = -1;
1383                                         }
1384                                         break;
1385                                 }
1386                                 default:
1387                                         break;
1388                                 }
1389
1390                                 g_assert (cfg->cbb == first_bb);
1391
1392                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1393                                         /* Replace the original instruction with the new code sequence */
1394
1395                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1396                                         first_bb->code = first_bb->last_ins = NULL;
1397                                         first_bb->in_count = first_bb->out_count = 0;
1398                                         cfg->cbb = first_bb;
1399                                 }
1400                                 else
1401                                         prev = ins;
1402                         }
1403                 }
1404
1405                 if (cfg->verbose_level > 2) mono_print_bb (bb, "AFTER LOWER-VTYPE-OPTS ");
1406         }
1407 }
1408
1409 void
1410 mono_decompose_vtype_opts_llvm (MonoCompile *cfg)
1411 {
1412         MonoBasicBlock *bb, *first_bb;
1413
1414         /* Decompose only the OP_STOREV_MEMBASE opcodes, which need write barriers */
1415
1416         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1417         first_bb = cfg->cbb;
1418
1419         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1420                 MonoInst *ins;
1421                 MonoInst *prev = NULL;
1422                 MonoInst *src_var, *src, *dest;
1423                 gboolean restart;
1424                 int dreg;
1425
1426                 if (cfg->verbose_level > 2) mono_print_bb (bb, "BEFORE LOWER-VTYPE-OPTS(LLVM) ");
1427
1428                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1429                 restart = TRUE;
1430
1431                 while (restart) {
1432                         restart = FALSE;
1433
1434                         for (ins = bb->code; ins; ins = ins->next) {
1435                                 switch (ins->opcode) {
1436                                 case OP_STOREV_MEMBASE: {
1437                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1438
1439                                         if (!src_var) {
1440                                                 g_assert (ins->klass);
1441                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1442                                         }
1443
1444                                         EMIT_NEW_VARLOADA_VREG ((cfg), (src), ins->sreg1, &ins->klass->byval_arg);
1445
1446                                         dreg = alloc_preg (cfg);
1447                                         EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
1448                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1449                                         break;
1450                                 }
1451                                 default:
1452                                         break;
1453                                 }
1454
1455                                 g_assert (cfg->cbb == first_bb);
1456
1457                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1458                                         /* Replace the original instruction with the new code sequence */
1459
1460                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1461                                         first_bb->code = first_bb->last_ins = NULL;
1462                                         first_bb->in_count = first_bb->out_count = 0;
1463                                         cfg->cbb = first_bb;
1464                                 }
1465                                 else
1466                                         prev = ins;
1467                         }
1468                 }
1469
1470                 if (cfg->verbose_level > 2) mono_print_bb (bb, "AFTER LOWER-VTYPE-OPTS(LLVM) ");
1471         }
1472 }
1473
1474 inline static MonoInst *
1475 mono_get_domainvar (MonoCompile *cfg)
1476 {
1477         if (!cfg->domainvar)
1478                 cfg->domainvar = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
1479         return cfg->domainvar;
1480 }
1481
1482 /**
1483  * mono_decompose_array_access_opts:
1484  *
1485  *  Decompose array access opcodes.
1486  */
1487 void
1488 mono_decompose_array_access_opts (MonoCompile *cfg)
1489 {
1490         MonoBasicBlock *bb, *first_bb;
1491
1492         /*
1493          * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it 
1494          * can be executed anytime. It should be run before decompose_long
1495          */
1496
1497         /**
1498          * Create a dummy bblock and emit code into it so we can use the normal 
1499          * code generation macros.
1500          */
1501         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1502         first_bb = cfg->cbb;
1503
1504         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1505                 MonoInst *ins;
1506                 MonoInst *prev = NULL;
1507                 MonoInst *dest;
1508                 MonoInst *iargs [3];
1509                 gboolean restart;
1510
1511                 if (!bb->has_array_access)
1512                         continue;
1513
1514                 if (cfg->verbose_level > 3) mono_print_bb (bb, "BEFORE DECOMPOSE-ARRAY-ACCESS-OPTS ");
1515
1516                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1517                 restart = TRUE;
1518
1519                 while (restart) {
1520                         restart = FALSE;
1521
1522                         for (ins = bb->code; ins; ins = ins->next) {
1523                                 switch (ins->opcode) {
1524                                 case OP_LDLEN:
1525                                         NEW_LOAD_MEMBASE_FLAGS (cfg, dest, OP_LOADI4_MEMBASE, ins->dreg, ins->sreg1,
1526                                                                                         G_STRUCT_OFFSET (MonoArray, max_length), ins->flags | MONO_INST_INVARIANT_LOAD);
1527                                         MONO_ADD_INS (cfg->cbb, dest);
1528                                         break;
1529                                 case OP_BOUNDS_CHECK:
1530                                         MONO_EMIT_NULL_CHECK (cfg, ins->sreg1);
1531                                         if (COMPILE_LLVM (cfg))
1532                                                 MONO_EMIT_DEFAULT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2, ins->flags & MONO_INST_FAULT);
1533                                         else
1534                                                 MONO_ARCH_EMIT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2);
1535                                         break;
1536                                 case OP_NEWARR:
1537                                         if (cfg->opt & MONO_OPT_SHARED) {
1538                                                 EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
1539                                                 EMIT_NEW_CLASSCONST (cfg, iargs [1], ins->inst_newa_class);
1540                                                 MONO_INST_NEW (cfg, iargs [2], OP_MOVE);
1541                                                 iargs [2]->dreg = ins->sreg1;
1542
1543                                                 dest = mono_emit_jit_icall (cfg, mono_array_new, iargs);
1544                                                 dest->dreg = ins->dreg;
1545                                         } else {
1546                                                 MonoClass *array_class = mono_array_class_get (ins->inst_newa_class, 1);
1547                                                 MonoVTable *vtable = mono_class_vtable (cfg->domain, array_class);
1548                                                 MonoMethod *managed_alloc = mono_gc_get_managed_array_allocator (array_class);
1549
1550                                                 g_assert (vtable); /*This shall not fail since we check for this condition on OP_NEWARR creation*/
1551                                                 NEW_VTABLECONST (cfg, iargs [0], vtable);
1552                                                 MONO_ADD_INS (cfg->cbb, iargs [0]);
1553                                                 MONO_INST_NEW (cfg, iargs [1], OP_MOVE);
1554                                                 iargs [1]->dreg = ins->sreg1;
1555
1556                                                 if (managed_alloc)
1557                                                         dest = mono_emit_method_call (cfg, managed_alloc, iargs, NULL);
1558                                                 else
1559                                                         dest = mono_emit_jit_icall (cfg, mono_array_new_specific, iargs);
1560                                                 dest->dreg = ins->dreg;
1561                                         }
1562                                         break;
1563                                 case OP_STRLEN:
1564                                         MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS (cfg, OP_LOADI4_MEMBASE, ins->dreg,
1565                                                                                                                  ins->sreg1, G_STRUCT_OFFSET (MonoString, length), ins->flags | MONO_INST_INVARIANT_LOAD);
1566                                         break;
1567                                 default:
1568                                         break;
1569                                 }
1570
1571                                 g_assert (cfg->cbb == first_bb);
1572
1573                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1574                                         /* Replace the original instruction with the new code sequence */
1575
1576                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1577                                         first_bb->code = first_bb->last_ins = NULL;
1578                                         first_bb->in_count = first_bb->out_count = 0;
1579                                         cfg->cbb = first_bb;
1580                                 }
1581                                 else
1582                                         prev = ins;
1583                         }
1584                 }
1585
1586                 if (cfg->verbose_level > 3) mono_print_bb (bb, "AFTER DECOMPOSE-ARRAY-ACCESS-OPTS ");
1587         }
1588 }
1589
1590 typedef union {
1591         guint32 vali [2];
1592         gint64 vall;
1593         double vald;
1594 } DVal;
1595
1596 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
1597
1598 /**
1599  * mono_decompose_soft_float:
1600  *
1601  *  Soft float support on ARM. We store each double value in a pair of integer vregs,
1602  * similar to long support on 32 bit platforms. 32 bit float values require special
1603  * handling when used as locals, arguments, and in calls.
1604  * One big problem with soft-float is that there are few r4 test cases in our test suite.
1605  */
1606 void
1607 mono_decompose_soft_float (MonoCompile *cfg)
1608 {
1609         MonoBasicBlock *bb, *first_bb;
1610
1611         /*
1612          * This pass creates long opcodes, so it should be run before decompose_long_opts ().
1613          */
1614
1615         /**
1616          * Create a dummy bblock and emit code into it so we can use the normal 
1617          * code generation macros.
1618          */
1619         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1620         first_bb = cfg->cbb;
1621
1622         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1623                 MonoInst *ins;
1624                 MonoInst *prev = NULL;
1625                 gboolean restart;
1626
1627                 if (cfg->verbose_level > 3) mono_print_bb (bb, "BEFORE HANDLE-SOFT-FLOAT ");
1628
1629                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1630                 restart = TRUE;
1631
1632                 while (restart) {
1633                         restart = FALSE;
1634
1635                         for (ins = bb->code; ins; ins = ins->next) {
1636                                 const char *spec = INS_INFO (ins->opcode);
1637
1638                                 /* Most fp operations are handled automatically by opcode emulation */
1639
1640                                 switch (ins->opcode) {
1641                                 case OP_R8CONST: {
1642                                         DVal d;
1643                                         d.vald = *(double*)ins->inst_p0;
1644                                         MONO_EMIT_NEW_I8CONST (cfg, ins->dreg, d.vall);
1645                                         break;
1646                                 }
1647                                 case OP_R4CONST: {
1648                                         DVal d;
1649                                         /* We load the r8 value */
1650                                         d.vald = *(float*)ins->inst_p0;
1651                                         MONO_EMIT_NEW_I8CONST (cfg, ins->dreg, d.vall);
1652                                         break;
1653                                 }
1654                                 case OP_FMOVE:
1655                                         ins->opcode = OP_LMOVE;
1656                                         break;
1657                                 case OP_FGETLOW32:
1658                                         ins->opcode = OP_MOVE;
1659                                         ins->sreg1 = ins->sreg1 + 1;
1660                                         break;
1661                                 case OP_FGETHIGH32:
1662                                         ins->opcode = OP_MOVE;
1663                                         ins->sreg1 = ins->sreg1 + 2;
1664                                         break;
1665                                 case OP_SETFRET: {
1666                                         int reg = ins->sreg1;
1667
1668                                         ins->opcode = OP_SETLRET;
1669                                         ins->dreg = -1;
1670                                         ins->sreg1 = reg + 1;
1671                                         ins->sreg2 = reg + 2;
1672                                         break;
1673                                 }
1674                                 case OP_LOADR8_MEMBASE:
1675                                         ins->opcode = OP_LOADI8_MEMBASE;
1676                                         break;
1677                                 case OP_STORER8_MEMBASE_REG:
1678                                         ins->opcode = OP_STOREI8_MEMBASE_REG;
1679                                         break;
1680                                 case OP_STORER4_MEMBASE_REG: {
1681                                         MonoInst *iargs [2];
1682                                         int addr_reg;
1683
1684                                         /* Arg 1 is the double value */
1685                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1686                                         iargs [0]->dreg = ins->sreg1;
1687
1688                                         /* Arg 2 is the address to store to */
1689                                         addr_reg = mono_alloc_preg (cfg);
1690                                         EMIT_NEW_BIALU_IMM (cfg, iargs [1], OP_PADD_IMM, addr_reg, ins->inst_destbasereg, ins->inst_offset);
1691                                         mono_emit_jit_icall (cfg, mono_fstore_r4, iargs);
1692                                         restart = TRUE;
1693                                         break;
1694                                 }
1695                                 case OP_LOADR4_MEMBASE: {
1696                                         MonoInst *iargs [1];
1697                                         MonoInst *conv;
1698                                         int addr_reg;
1699
1700                                         addr_reg = mono_alloc_preg (cfg);
1701                                         EMIT_NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, addr_reg, ins->inst_basereg, ins->inst_offset);
1702                                         conv = mono_emit_jit_icall (cfg, mono_fload_r4, iargs);
1703                                         conv->dreg = ins->dreg;
1704                                         break;
1705                                 }                                       
1706                                 case OP_FCALL:
1707                                 case OP_FCALL_REG:
1708                                 case OP_FCALL_MEMBASE: {
1709                                         MonoCallInst *call = (MonoCallInst*)ins;
1710                                         if (call->signature->ret->type == MONO_TYPE_R4) {
1711                                                 MonoCallInst *call2;
1712                                                 MonoInst *iargs [1];
1713                                                 MonoInst *conv;
1714                                                 GSList *l;
1715
1716                                                 /* Convert the call into a call returning an int */
1717                                                 MONO_INST_NEW_CALL (cfg, call2, OP_CALL);
1718                                                 memcpy (call2, call, sizeof (MonoCallInst));
1719                                                 switch (ins->opcode) {
1720                                                 case OP_FCALL:
1721                                                         call2->inst.opcode = OP_CALL;
1722                                                         break;
1723                                                 case OP_FCALL_REG:
1724                                                         call2->inst.opcode = OP_CALL_REG;
1725                                                         break;
1726                                                 case OP_FCALL_MEMBASE:
1727                                                         call2->inst.opcode = OP_CALL_MEMBASE;
1728                                                         break;
1729                                                 default:
1730                                                         g_assert_not_reached ();
1731                                                 }
1732                                                 call2->inst.dreg = mono_alloc_ireg (cfg);
1733                                                 MONO_ADD_INS (cfg->cbb, (MonoInst*)call2);
1734
1735                                                 /* Remap OUTARG_VT instructions referencing this call */
1736                                                 for (l = call->outarg_vts; l; l = l->next)
1737                                                         ((MonoInst*)(l->data))->inst_p0 = call2;
1738
1739                                                 /* FIXME: Optimize this */
1740
1741                                                 /* Emit an r4->r8 conversion */
1742                                                 EMIT_NEW_VARLOADA_VREG (cfg, iargs [0], call2->inst.dreg, &mono_defaults.int32_class->byval_arg);
1743                                                 conv = mono_emit_jit_icall (cfg, mono_fload_r4, iargs);
1744                                                 conv->dreg = ins->dreg;
1745
1746                                                 /* The call sequence might include fp ins */
1747                                                 restart = TRUE;
1748                                         } else {
1749                                                 switch (ins->opcode) {
1750                                                 case OP_FCALL:
1751                                                         ins->opcode = OP_LCALL;
1752                                                         break;
1753                                                 case OP_FCALL_REG:
1754                                                         ins->opcode = OP_LCALL_REG;
1755                                                         break;
1756                                                 case OP_FCALL_MEMBASE:
1757                                                         ins->opcode = OP_LCALL_MEMBASE;
1758                                                         break;
1759                                                 default:
1760                                                         g_assert_not_reached ();
1761                                                 }
1762                                         }
1763                                         break;
1764                                 }
1765                                 case OP_FCOMPARE: {
1766                                         MonoJitICallInfo *info;
1767                                         MonoInst *iargs [2];
1768                                         MonoInst *call, *cmp, *br;
1769
1770                                         /* Convert fcompare+fbcc to icall+icompare+beq */
1771
1772                                         if (!ins->next) {
1773                                                 /* The branch might be optimized away */
1774                                                 NULLIFY_INS (ins);
1775                                                 break;
1776                                         }
1777
1778                                         info = mono_find_jit_opcode_emulation (ins->next->opcode);
1779                                         if (!info) {
1780                                                 /* The branch might be optimized away */
1781                                                 NULLIFY_INS (ins);
1782                                                 break;
1783                                         }
1784
1785                                         /* Create dummy MonoInst's for the arguments */
1786                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1787                                         iargs [0]->dreg = ins->sreg1;
1788                                         MONO_INST_NEW (cfg, iargs [1], OP_ARG);
1789                                         iargs [1]->dreg = ins->sreg2;
1790
1791                                         call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, iargs);
1792
1793                                         MONO_INST_NEW (cfg, cmp, OP_ICOMPARE_IMM);
1794                                         cmp->sreg1 = call->dreg;
1795                                         cmp->inst_imm = 0;
1796                                         MONO_ADD_INS (cfg->cbb, cmp);
1797                                         
1798                                         MONO_INST_NEW (cfg, br, OP_IBNE_UN);
1799                                         br->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof (gpointer) * 2);
1800                                         br->inst_true_bb = ins->next->inst_true_bb;
1801                                         br->inst_false_bb = ins->next->inst_false_bb;
1802                                         MONO_ADD_INS (cfg->cbb, br);
1803
1804                                         /* The call sequence might include fp ins */
1805                                         restart = TRUE;
1806
1807                                         /* Skip fbcc or fccc */
1808                                         NULLIFY_INS (ins->next);
1809                                         break;
1810                                 }
1811                                 case OP_FCEQ:
1812                                 case OP_FCGT:
1813                                 case OP_FCGT_UN:
1814                                 case OP_FCLT:
1815                                 case OP_FCLT_UN: {
1816                                         MonoJitICallInfo *info;
1817                                         MonoInst *iargs [2];
1818                                         MonoInst *call;
1819
1820                                         /* Convert fccc to icall+icompare+iceq */
1821
1822                                         info = mono_find_jit_opcode_emulation (ins->opcode);
1823                                         g_assert (info);
1824
1825                                         /* Create dummy MonoInst's for the arguments */
1826                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1827                                         iargs [0]->dreg = ins->sreg1;
1828                                         MONO_INST_NEW (cfg, iargs [1], OP_ARG);
1829                                         iargs [1]->dreg = ins->sreg2;
1830
1831                                         call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, iargs);
1832
1833                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, call->dreg, 1);
1834                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, ins->dreg, -1);
1835
1836                                         /* The call sequence might include fp ins */
1837                                         restart = TRUE;
1838                                         break;
1839                                 }
1840                                 case OP_CKFINITE: {
1841                                         MonoInst *iargs [2];
1842                                         MonoInst *call, *cmp;
1843
1844                                         /* Convert to icall+icompare+cond_exc+move */
1845
1846                                         /* Create dummy MonoInst's for the arguments */
1847                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1848                                         iargs [0]->dreg = ins->sreg1;
1849
1850                                         call = mono_emit_jit_icall (cfg, mono_isfinite, iargs);
1851
1852                                         MONO_INST_NEW (cfg, cmp, OP_ICOMPARE_IMM);
1853                                         cmp->sreg1 = call->dreg;
1854                                         cmp->inst_imm = 1;
1855                                         MONO_ADD_INS (cfg->cbb, cmp);
1856
1857                                         MONO_EMIT_NEW_COND_EXC (cfg, INE_UN, "ArithmeticException");
1858
1859                                         /* Do the assignment if the value is finite */
1860                                         MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, ins->dreg, ins->sreg1);
1861
1862                                         restart = TRUE;
1863                                         break;
1864                                 }
1865                                 default:
1866                                         if (spec [MONO_INST_SRC1] == 'f' || spec [MONO_INST_SRC2] == 'f' || spec [MONO_INST_DEST] == 'f') {
1867                                                 mono_print_ins (ins);
1868                                                 g_assert_not_reached ();
1869                                         }
1870                                         break;
1871                                 }
1872
1873                                 g_assert (cfg->cbb == first_bb);
1874
1875                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1876                                         /* Replace the original instruction with the new code sequence */
1877
1878                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1879                                         first_bb->code = first_bb->last_ins = NULL;
1880                                         first_bb->in_count = first_bb->out_count = 0;
1881                                         cfg->cbb = first_bb;
1882                                 }
1883                                 else
1884                                         prev = ins;
1885                         }
1886                 }
1887
1888                 if (cfg->verbose_level > 3) mono_print_bb (bb, "AFTER HANDLE-SOFT-FLOAT ");
1889         }
1890
1891         mono_decompose_long_opts (cfg);
1892 }
1893
1894 #endif
1895
1896 #endif /* DISABLE_JIT */