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