Merge pull request #986 from ninjarobot/patch-1
[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_DUMMY_I8CONST:
578                                 MONO_EMIT_NEW_DUMMY_INIT (cfg, tree->dreg + 1, OP_DUMMY_ICONST);
579                                 MONO_EMIT_NEW_DUMMY_INIT (cfg, tree->dreg + 2, OP_DUMMY_ICONST);
580                                 break;
581                         case OP_LMOVE:
582                         case OP_LCONV_TO_U8:
583                         case OP_LCONV_TO_I8:
584                         case OP_LCONV_TO_OVF_U8_UN:
585                         case OP_LCONV_TO_OVF_I8:
586                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1);
587                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2);
588                                 break;
589                         case OP_STOREI8_MEMBASE_REG:
590                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_MS_WORD_OFFSET, tree->sreg1 + 2);
591                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_LS_WORD_OFFSET, tree->sreg1 + 1);
592                                 break;
593                         case OP_LOADI8_MEMBASE:
594                                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tree->dreg + 2, tree->inst_basereg, tree->inst_offset + MINI_MS_WORD_OFFSET);
595                                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tree->dreg + 1, tree->inst_basereg, tree->inst_offset + MINI_LS_WORD_OFFSET);
596                                 break;
597
598                         case OP_ICONV_TO_I8: {
599                                 guint32 tmpreg = alloc_ireg (cfg);
600
601                                 /* branchless code:
602                                  * low = reg;
603                                  * tmp = low > -1 ? 1: 0;
604                                  * high = tmp - 1; if low is zero or pos high becomes 0, else -1
605                                  */
606                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
607                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, tree->dreg + 1, -1);
608                                 MONO_EMIT_NEW_BIALU (cfg, OP_ICGT, tmpreg, -1, -1);
609                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISUB_IMM, tree->dreg + 2, tmpreg, 1);
610                                 break;
611                         }
612                         case OP_ICONV_TO_U8:
613                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
614                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
615                                 break;
616                         case OP_ICONV_TO_OVF_I8:
617                                 /* a signed 32 bit num always fits in a signed 64 bit one */
618                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, tree->dreg + 2, tree->sreg1, 31);
619                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
620                                 break;
621                         case OP_ICONV_TO_OVF_U8:
622                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1, 0);
623                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
624                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
625                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
626                                 break;
627                         case OP_ICONV_TO_OVF_I8_UN:
628                         case OP_ICONV_TO_OVF_U8_UN:
629                                 /* an unsigned 32 bit num always fits in an (un)signed 64 bit one */
630                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
631                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
632                                 break;
633                         case OP_LCONV_TO_I1:
634                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1);
635                                 break;
636                         case OP_LCONV_TO_U1:
637                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U1, tree->dreg, tree->sreg1 + 1);
638                                 break;
639                         case OP_LCONV_TO_I2:
640                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1);
641                                 break;
642                         case OP_LCONV_TO_U2:
643                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U2, tree->dreg, tree->sreg1 + 1);
644                                 break;
645                         case OP_LCONV_TO_I4:
646                         case OP_LCONV_TO_U4:
647                         case OP_LCONV_TO_I:
648                         case OP_LCONV_TO_U:
649                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1);
650                                 break;
651                         case OP_LCONV_TO_R8:
652                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R8_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
653                                 break;
654                         case OP_LCONV_TO_R4:
655                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R4_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
656                                 break;
657                         case OP_LCONV_TO_R_UN:
658                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R_UN_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
659                                 break;
660                         case OP_LCONV_TO_OVF_I1: {
661                                 MonoBasicBlock *is_negative, *end_label;
662
663                                 NEW_BBLOCK (cfg, is_negative);
664                                 NEW_BBLOCK (cfg, end_label);
665
666                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
667                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
668                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, -1);
669                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
670
671                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
672                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative);
673
674                                 /* Positive */
675                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 127);
676                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
677                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label);
678
679                                 /* Negative */
680                                 MONO_START_BB (cfg, is_negative);
681                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -128);
682                                 MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException");
683
684                                 MONO_START_BB (cfg, end_label);
685
686                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1);
687                                 break;
688                         }
689                         case OP_LCONV_TO_OVF_I1_UN:
690                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
691                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
692
693                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 127);
694                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
695                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -128);
696                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
697                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1);
698                                 break;
699                         case OP_LCONV_TO_OVF_U1:
700                         case OP_LCONV_TO_OVF_U1_UN:
701                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
702                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
703
704                                 /* probe value to be within 0 to 255 */
705                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 255);
706                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
707                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, tree->sreg1 + 1, 0xff);
708                                 break;
709                         case OP_LCONV_TO_OVF_I2: {
710                                 MonoBasicBlock *is_negative, *end_label;
711
712                                 NEW_BBLOCK (cfg, is_negative);
713                                 NEW_BBLOCK (cfg, end_label);
714
715                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
716                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
717                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, -1);
718                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
719
720                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
721                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative);
722
723                                 /* Positive */
724                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 32767);
725                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
726                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label);
727
728                                 /* Negative */
729                                 MONO_START_BB (cfg, is_negative);
730                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -32768);
731                                 MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException");
732                                 MONO_START_BB (cfg, end_label);
733
734                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1);
735                                 break;
736                         }
737                         case OP_LCONV_TO_OVF_I2_UN:
738                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
739                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
740
741                                 /* Probe value to be within -32768 and 32767 */
742                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 32767);
743                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
744                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -32768);
745                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
746                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1);
747                                 break;
748                         case OP_LCONV_TO_OVF_U2:
749                         case OP_LCONV_TO_OVF_U2_UN:
750                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
751                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
752
753                                 /* Probe value to be within 0 and 65535 */
754                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 0xffff);
755                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
756                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, tree->sreg1 + 1, 0xffff);
757                                 break;
758                         case OP_LCONV_TO_OVF_I4:
759                         case OP_LCONV_TO_OVF_I:
760                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_OVF_I4_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
761                                 break;
762                         case OP_LCONV_TO_OVF_U4:
763                         case OP_LCONV_TO_OVF_U:
764                         case OP_LCONV_TO_OVF_U4_UN:
765                         case OP_LCONV_TO_OVF_U_UN:
766                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
767                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
768                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1);
769                                 break;
770                         case OP_LCONV_TO_OVF_I_UN:
771                         case OP_LCONV_TO_OVF_I4_UN:
772                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
773                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
774                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 1, 0);
775                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
776                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1);
777                                 break;
778                         case OP_LCONV_TO_OVF_U8:
779                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
780                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
781
782                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1);
783                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2);
784                                 break;
785                         case OP_LCONV_TO_OVF_I8_UN:
786                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
787                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
788
789                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1);
790                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2);
791                                 break;
792
793                         case OP_LADD:
794                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
795                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
796                                 break;
797                         case OP_LSUB:
798                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
799                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
800                                 break;
801
802                         case OP_LADD_OVF:
803                                 /* ADC sets the condition code */
804                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
805                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
806                                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
807                                 break;
808                         case OP_LADD_OVF_UN:
809                                 /* ADC sets the condition code */
810                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
811                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
812                                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
813                                 break;
814                         case OP_LSUB_OVF:
815                                 /* SBB sets the condition code */
816                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
817                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
818                                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
819                                 break;
820                         case OP_LSUB_OVF_UN:
821                                 /* SBB sets the condition code */
822                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
823                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
824                                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
825                                 break;
826                         case OP_LAND:
827                                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
828                                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
829                                 break;
830                         case OP_LOR:
831                                 MONO_EMIT_NEW_BIALU (cfg, OP_IOR, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
832                                 MONO_EMIT_NEW_BIALU (cfg, OP_IOR, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
833                                 break;
834                         case OP_LXOR:
835                                 MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
836                                 MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
837                                 break;
838                         case OP_LNOT:
839                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 1, tree->sreg1 + 1);
840                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 2, tree->sreg1 + 2);
841                                 break;
842                         case OP_LNEG:
843                                 /* Handled in mono_arch_decompose_long_opts () */
844                                 g_assert_not_reached ();
845                                 break;
846                         case OP_LMUL:
847                                 /* Emulated */
848                                 /* FIXME: Add OP_BIGMUL optimization */
849                                 break;
850
851                         case OP_LADD_IMM:
852                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADDCC_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
853                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
854                                 break;
855                         case OP_LSUB_IMM:
856                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUBCC_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
857                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SBB_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
858                                 break;
859                         case OP_LAND_IMM:
860                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
861                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
862                                 break;
863                         case OP_LOR_IMM:
864                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
865                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
866                                 break;
867                         case OP_LXOR_IMM:
868                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
869                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
870                                 break;
871                         case OP_LSHR_UN_IMM:
872                                 if (tree->inst_c1 == 32) {
873
874                                         /* The original code had this comment: */
875                                         /* special case that gives a nice speedup and happens to workaorund a ppc jit but (for the release)
876                                          * later apply the speedup to the left shift as well
877                                          * See BUG# 57957.
878                                          */
879                                         /* FIXME: Move this to the strength reduction pass */
880                                         /* just move the upper half to the lower and zero the high word */
881                                         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 2);
882                                         MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
883                                 }
884                                 break;
885                         case OP_LSHL_IMM:
886                                 if (tree->inst_c1 == 32) {
887                                         /* just move the lower half to the upper and zero the lower word */
888                                         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 1);
889                                         MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 1, 0);
890                                 }
891                                 break;
892
893                         case OP_LCOMPARE: {
894                                 MonoInst *next = tree->next;
895
896                                 g_assert (next);
897
898                                 switch (next->opcode) {
899                                 case OP_LBEQ:
900                                 case OP_LBNE_UN: {
901                                         int d1, d2;
902
903                                         /* Branchless version based on gcc code */
904                                         d1 = alloc_ireg (cfg);
905                                         d2 = alloc_ireg (cfg);
906                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, tree->sreg1 + 1, tree->sreg2 + 1);
907                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, tree->sreg1 + 2, tree->sreg2 + 2);
908                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
909                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
910                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
911                                         next->opcode = OP_NOP;
912                                         break;
913                                 }
914                                 case OP_LBGE:
915                                 case OP_LBGT:
916                                 case OP_LBLE:
917                                 case OP_LBLT:
918                                 case OP_LBGE_UN:
919                                 case OP_LBGT_UN:
920                                 case OP_LBLE_UN:
921                                 case OP_LBLT_UN:
922                                         /* Convert into three comparisons + branches */
923                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
924                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lbr_decomp [next->opcode - OP_LBEQ][0], next->inst_true_bb);
925                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
926                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
927                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1);
928                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
929                                         next->opcode = OP_NOP;
930                                         break;
931                                 case OP_LCEQ: {
932                                         int d1, d2;
933         
934                                         /* Branchless version based on gcc code */
935                                         d1 = alloc_ireg (cfg);
936                                         d2 = alloc_ireg (cfg);
937                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, tree->sreg1 + 1, tree->sreg2 + 1);
938                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, tree->sreg1 + 2, tree->sreg2 + 2);
939                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
940
941                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
942                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
943                                         next->opcode = OP_NOP;
944                                         break;
945                                 }
946                                 case OP_LCLT:
947                                 case OP_LCLT_UN:
948                                 case OP_LCGT:
949                                 case OP_LCGT_UN: {
950                                         MonoBasicBlock *set_to_0, *set_to_1;
951         
952                                         NEW_BBLOCK (cfg, set_to_0);
953                                         NEW_BBLOCK (cfg, set_to_1);
954
955                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 0);
956                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
957                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][0], set_to_0);
958                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
959                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, set_to_1);
960                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1);
961                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][1], set_to_0);
962                                         MONO_START_BB (cfg, set_to_1);
963                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
964                                         MONO_START_BB (cfg, set_to_0);
965                                         next->opcode = OP_NOP;
966                                         break;  
967                                 }
968                                 default:
969                                         g_assert_not_reached ();
970                                 }
971                                 break;
972                         }
973
974                         /* Not yet used, since lcompare is decomposed before local cprop */
975                         case OP_LCOMPARE_IMM: {
976                                 MonoInst *next = tree->next;
977                                 guint32 low_imm = tree->inst_ls_word;
978                                 guint32 high_imm = tree->inst_ms_word;
979                                 int low_reg = tree->sreg1 + 1;
980                                 int high_reg = tree->sreg1 + 2;
981
982                                 g_assert (next);
983
984                                 switch (next->opcode) {
985                                 case OP_LBEQ:
986                                 case OP_LBNE_UN: {
987                                         int d1, d2;
988
989                                         /* Branchless version based on gcc code */
990                                         d1 = alloc_ireg (cfg);
991                                         d2 = alloc_ireg (cfg);
992                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d1, low_reg, low_imm);
993                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d2, high_reg, high_imm);
994                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
995                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
996                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
997                                         next->opcode = OP_NOP;
998                                         break;
999                                 }
1000
1001                                 case OP_LBGE:
1002                                 case OP_LBGT:
1003                                 case OP_LBLE:
1004                                 case OP_LBLT:
1005                                 case OP_LBGE_UN:
1006                                 case OP_LBGT_UN:
1007                                 case OP_LBLE_UN:
1008                                 case OP_LBLT_UN:
1009                                         /* Convert into three comparisons + branches */
1010                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1011                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lbr_decomp [next->opcode - OP_LBEQ][0], next->inst_true_bb);
1012                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1013                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
1014                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
1015                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
1016                                         next->opcode = OP_NOP;
1017                                         break;
1018                                 case OP_LCEQ: {
1019                                         int d1, d2;
1020         
1021                                         /* Branchless version based on gcc code */
1022                                         d1 = alloc_ireg (cfg);
1023                                         d2 = alloc_ireg (cfg);
1024                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d1, low_reg, low_imm);
1025                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d2, high_reg, high_imm);
1026                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
1027
1028                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
1029                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
1030                                         next->opcode = OP_NOP;
1031                                         break;
1032                                 }
1033                                 case OP_LCLT:
1034                                 case OP_LCLT_UN:
1035                                 case OP_LCGT:
1036                                 case OP_LCGT_UN: {
1037                                         MonoBasicBlock *set_to_0, *set_to_1;
1038         
1039                                         NEW_BBLOCK (cfg, set_to_0);
1040                                         NEW_BBLOCK (cfg, set_to_1);
1041
1042                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 0);
1043                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1044                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][0], set_to_0);
1045                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1046                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, set_to_1);
1047                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
1048                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][1], set_to_0);
1049                                         MONO_START_BB (cfg, set_to_1);
1050                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
1051                                         MONO_START_BB (cfg, set_to_0);
1052                                         next->opcode = OP_NOP;
1053                                         break;  
1054                                 }
1055                                 default:
1056                                         g_assert_not_reached ();
1057                                 }
1058                                 break;
1059                         }
1060
1061                         default:
1062                                 break;
1063                         }
1064
1065                         if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1066                                 MonoInst *new_prev;
1067
1068                                 /* Replace the original instruction with the new code sequence */
1069
1070                                 /* Ignore the new value of prev */
1071                                 new_prev = prev;
1072                                 mono_replace_ins (cfg, bb, tree, &new_prev, first_bb, cfg->cbb);
1073
1074                                 /* Process the newly added ops again since they can be long ops too */
1075                                 if (prev)
1076                                         tree = prev->next;
1077                                 else
1078                                         tree = bb->code;
1079
1080                                 first_bb->code = first_bb->last_ins = NULL;
1081                                 first_bb->in_count = first_bb->out_count = 0;
1082                                 cfg->cbb = first_bb;
1083                         }
1084                         else {
1085                                 prev = tree;
1086                                 tree = tree->next;
1087                         }
1088                 }
1089         }
1090 #endif
1091
1092         /*
1093         for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
1094                 mono_print_bb (bb, "AFTER LOWER-LONG-OPTS");
1095         */
1096 }
1097
1098 /**
1099  * mono_decompose_vtype_opts:
1100  *
1101  *  Decompose valuetype opcodes.
1102  */
1103 void
1104 mono_decompose_vtype_opts (MonoCompile *cfg)
1105 {
1106         MonoBasicBlock *bb, *first_bb;
1107
1108         /**
1109          * Using OP_V opcodes and decomposing them later have two main benefits:
1110          * - it simplifies method_to_ir () since there is no need to special-case vtypes
1111          *   everywhere.
1112          * - it gets rid of the LDADDR opcodes generated when vtype operations are decomposed,
1113          *   enabling optimizations to work on vtypes too.
1114          * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it 
1115          * can be executed anytime. It should be executed as late as possible so vtype
1116          * opcodes can be optimized by the other passes.
1117          * The pinvoke wrappers need to manipulate vtypes in their unmanaged representation.
1118          * This is indicated by setting the 'backend.is_pinvoke' field of the MonoInst for the 
1119          * var to 1.
1120          * This is done on demand, ie. by the LDNATIVEOBJ opcode, and propagated by this pass 
1121          * when OP_VMOVE opcodes are decomposed.
1122          */
1123
1124         /* 
1125          * Vregs have no associated type information, so we store the type of the vregs
1126          * in ins->klass.
1127          */
1128
1129         /**
1130          * Create a dummy bblock and emit code into it so we can use the normal 
1131          * code generation macros.
1132          */
1133         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1134         first_bb = cfg->cbb;
1135
1136         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1137                 MonoInst *ins;
1138                 MonoInst *prev = NULL;
1139                 MonoInst *src_var, *dest_var, *src, *dest;
1140                 gboolean restart;
1141                 int dreg;
1142
1143                 if (cfg->verbose_level > 2) mono_print_bb (bb, "BEFORE LOWER-VTYPE-OPTS ");
1144
1145                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1146                 restart = TRUE;
1147
1148                 while (restart) {
1149                         restart = FALSE;
1150
1151                         for (ins = bb->code; ins; ins = ins->next) {
1152                                 switch (ins->opcode) {
1153                                 case OP_VMOVE: {
1154                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1155                                         dest_var = get_vreg_to_inst (cfg, ins->dreg);
1156
1157                                         g_assert (ins->klass);
1158
1159                                         if (!src_var)
1160                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1161
1162                                         if (!dest_var)
1163                                                 dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1164
1165                                         // FIXME:
1166                                         if (src_var->backend.is_pinvoke)
1167                                                 dest_var->backend.is_pinvoke = 1;
1168
1169                                         EMIT_NEW_VARLOADA ((cfg), (src), src_var, src_var->inst_vtype);
1170                                         EMIT_NEW_VARLOADA ((cfg), (dest), dest_var, dest_var->inst_vtype);
1171
1172                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1173                                         break;
1174                                 }
1175                                 case OP_VZERO:
1176                                         g_assert (ins->klass);
1177
1178                                         EMIT_NEW_VARLOADA_VREG (cfg, dest, ins->dreg, &ins->klass->byval_arg);
1179                                         mini_emit_initobj (cfg, dest, NULL, ins->klass);
1180                                         
1181                                         if (cfg->compute_gc_maps) {
1182                                                 MonoInst *tmp;
1183
1184                                                 /* 
1185                                                  * Tell the GC map code that the vtype is considered live after
1186                                                  * the initialization.
1187                                                  */
1188                                                 MONO_INST_NEW (cfg, tmp, OP_GC_LIVENESS_DEF);
1189                                                 tmp->inst_c1 = ins->dreg;
1190                                                 MONO_ADD_INS (cfg->cbb, tmp);
1191                                         }
1192                                         break;
1193                                 case OP_DUMMY_VZERO:
1194                                         NULLIFY_INS (ins);
1195                                         break;
1196                                 case OP_STOREV_MEMBASE: {
1197                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1198
1199                                         if (!src_var) {
1200                                                 g_assert (ins->klass);
1201                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1202                                         }
1203
1204                                         EMIT_NEW_VARLOADA_VREG ((cfg), (src), ins->sreg1, &ins->klass->byval_arg);
1205
1206                                         dreg = alloc_preg (cfg);
1207                                         EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
1208                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1209                                         break;
1210                                 }
1211                                 case OP_LOADV_MEMBASE: {
1212                                         g_assert (ins->klass);
1213
1214                                         dest_var = get_vreg_to_inst (cfg, ins->dreg);
1215                                         // FIXME-VT:
1216                                         // FIXME:
1217                                         if (!dest_var)
1218                                                 dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1219
1220                                         dreg = alloc_preg (cfg);
1221                                         EMIT_NEW_BIALU_IMM (cfg, src, OP_ADD_IMM, dreg, ins->inst_basereg, ins->inst_offset);
1222                                         EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
1223                                         mini_emit_stobj (cfg, dest, src, dest_var->klass, dest_var->backend.is_pinvoke);
1224                                         break;
1225                                 }
1226                                 case OP_OUTARG_VT: {
1227                                         g_assert (ins->klass);
1228
1229                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1230                                         if (!src_var)
1231                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1232                                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
1233
1234                                         mono_arch_emit_outarg_vt (cfg, ins, src);
1235
1236                                         /* This might be decomposed into other vtype opcodes */
1237                                         restart = TRUE;
1238                                         break;
1239                                 }
1240                                 case OP_OUTARG_VTRETADDR: {
1241                                         MonoCallInst *call = (MonoCallInst*)ins->inst_p1;
1242
1243                                         src_var = get_vreg_to_inst (cfg, call->inst.dreg);
1244                                         if (!src_var)
1245                                                 src_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
1246                                         // FIXME: src_var->backend.is_pinvoke ?
1247
1248                                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
1249                                         src->dreg = ins->dreg;
1250                                         break;
1251                                 }
1252                                 case OP_VCALL:
1253                                 case OP_VCALL_REG:
1254                                 case OP_VCALL_MEMBASE: {
1255                                         MonoCallInst *call = (MonoCallInst*)ins;
1256                                         int size;
1257
1258                                         if (call->vret_in_reg) {
1259                                                 MonoCallInst *call2;
1260
1261                                                 /* Replace the vcall with an integer call */
1262                                                 MONO_INST_NEW_CALL (cfg, call2, OP_NOP);
1263                                                 memcpy (call2, call, sizeof (MonoCallInst));
1264                                                 switch (ins->opcode) {
1265                                                 case OP_VCALL:
1266                                                         call2->inst.opcode = OP_CALL;
1267                                                         break;
1268                                                 case OP_VCALL_REG:
1269                                                         call2->inst.opcode = OP_CALL_REG;
1270                                                         break;
1271                                                 case OP_VCALL_MEMBASE:
1272                                                         call2->inst.opcode = OP_CALL_MEMBASE;
1273                                                         break;
1274                                                 }
1275                                                 call2->inst.dreg = alloc_preg (cfg);
1276                                                 MONO_ADD_INS (cfg->cbb, ((MonoInst*)call2));
1277
1278                                                 /* Compute the vtype location */
1279                                                 dest_var = get_vreg_to_inst (cfg, call->inst.dreg);
1280                                                 if (!dest_var)
1281                                                         dest_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
1282                                                 EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
1283
1284                                                 /* Save the result */
1285                                                 if (dest_var->backend.is_pinvoke)
1286                                                         size = mono_class_native_size (mono_class_from_mono_type (dest_var->inst_vtype), NULL);
1287                                                 else
1288                                                         size = mono_type_size (dest_var->inst_vtype, NULL);
1289                                                 switch (size) {
1290                                                 case 1:
1291                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1292                                                         break;
1293                                                 case 2:
1294                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1295                                                         break;
1296                                                 case 3:
1297                                                 case 4:
1298                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1299                                                         break;
1300                                                 case 5:
1301                                                 case 6:
1302                                                 case 7:
1303                                                 case 8:
1304 #if SIZEOF_REGISTER == 4
1305                                                         /*
1306                                                         FIXME Other ABIs might return in different regs than the ones used for LCALL.
1307                                                         FIXME It would be even nicer to be able to leverage the long decompose stuff.
1308                                                         */
1309                                                         switch (call2->inst.opcode) {
1310                                                         case OP_CALL:
1311                                                                 call2->inst.opcode = OP_LCALL;
1312                                                                 break;
1313                                                         case OP_CALL_REG:
1314                                                                 call2->inst.opcode = OP_LCALL_REG;
1315                                                                 break;
1316                                                         case OP_CALL_MEMBASE:
1317                                                                 call2->inst.opcode = OP_LCALL_MEMBASE;
1318                                                                 break;
1319                                                         }
1320                                                         call2->inst.dreg = alloc_lreg (cfg);
1321                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_MS_WORD_OFFSET, call2->inst.dreg + 2);
1322                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_LS_WORD_OFFSET, call2->inst.dreg + 1);
1323 #else
1324                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1325 #endif
1326                                                         break;
1327                                                 default:
1328                                                         /* This assumes the vtype is sizeof (gpointer) long */
1329                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1330                                                         break;
1331                                                 }
1332                                         } else {
1333                                                 switch (ins->opcode) {
1334                                                 case OP_VCALL:
1335                                                         ins->opcode = OP_VCALL2;
1336                                                         break;
1337                                                 case OP_VCALL_REG:
1338                                                         ins->opcode = OP_VCALL2_REG;
1339                                                         break;
1340                                                 case OP_VCALL_MEMBASE:
1341                                                         ins->opcode = OP_VCALL2_MEMBASE;
1342                                                         break;
1343                                                 }
1344                                                 ins->dreg = -1;
1345                                         }
1346                                         break;
1347                                 }
1348                                 default:
1349                                         break;
1350                                 }
1351
1352                                 g_assert (cfg->cbb == first_bb);
1353
1354                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1355                                         /* Replace the original instruction with the new code sequence */
1356
1357                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1358                                         first_bb->code = first_bb->last_ins = NULL;
1359                                         first_bb->in_count = first_bb->out_count = 0;
1360                                         cfg->cbb = first_bb;
1361                                 }
1362                                 else
1363                                         prev = ins;
1364                         }
1365                 }
1366
1367                 if (cfg->verbose_level > 2) mono_print_bb (bb, "AFTER LOWER-VTYPE-OPTS ");
1368         }
1369 }
1370
1371 void
1372 mono_decompose_vtype_opts_llvm (MonoCompile *cfg)
1373 {
1374         MonoBasicBlock *bb, *first_bb;
1375
1376         /* Decompose only the OP_STOREV_MEMBASE opcodes, which need write barriers */
1377
1378         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1379         first_bb = cfg->cbb;
1380
1381         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1382                 MonoInst *ins;
1383                 MonoInst *prev = NULL;
1384                 MonoInst *src_var, *src, *dest;
1385                 gboolean restart;
1386                 int dreg;
1387
1388                 if (cfg->verbose_level > 2) mono_print_bb (bb, "BEFORE LOWER-VTYPE-OPTS(LLVM) ");
1389
1390                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1391                 restart = TRUE;
1392
1393                 while (restart) {
1394                         restart = FALSE;
1395
1396                         for (ins = bb->code; ins; ins = ins->next) {
1397                                 switch (ins->opcode) {
1398                                 case OP_STOREV_MEMBASE: {
1399                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1400
1401                                         if (!src_var) {
1402                                                 g_assert (ins->klass);
1403                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1404                                         }
1405
1406                                         EMIT_NEW_VARLOADA_VREG ((cfg), (src), ins->sreg1, &ins->klass->byval_arg);
1407
1408                                         dreg = alloc_preg (cfg);
1409                                         EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
1410                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1411                                         break;
1412                                 }
1413                                 default:
1414                                         break;
1415                                 }
1416
1417                                 g_assert (cfg->cbb == first_bb);
1418
1419                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1420                                         /* Replace the original instruction with the new code sequence */
1421
1422                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1423                                         first_bb->code = first_bb->last_ins = NULL;
1424                                         first_bb->in_count = first_bb->out_count = 0;
1425                                         cfg->cbb = first_bb;
1426                                 }
1427                                 else
1428                                         prev = ins;
1429                         }
1430                 }
1431
1432                 if (cfg->verbose_level > 2) mono_print_bb (bb, "AFTER LOWER-VTYPE-OPTS(LLVM) ");
1433         }
1434 }
1435
1436 inline static MonoInst *
1437 mono_get_domainvar (MonoCompile *cfg)
1438 {
1439         if (!cfg->domainvar)
1440                 cfg->domainvar = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
1441         return cfg->domainvar;
1442 }
1443
1444 /**
1445  * mono_decompose_array_access_opts:
1446  *
1447  *  Decompose array access opcodes.
1448  */
1449 void
1450 mono_decompose_array_access_opts (MonoCompile *cfg)
1451 {
1452         MonoBasicBlock *bb, *first_bb;
1453
1454         /*
1455          * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it 
1456          * can be executed anytime. It should be run before decompose_long
1457          */
1458
1459         /**
1460          * Create a dummy bblock and emit code into it so we can use the normal 
1461          * code generation macros.
1462          */
1463         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1464         first_bb = cfg->cbb;
1465
1466         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1467                 MonoInst *ins;
1468                 MonoInst *prev = NULL;
1469                 MonoInst *dest;
1470                 MonoInst *iargs [3];
1471                 gboolean restart;
1472
1473                 if (!bb->has_array_access)
1474                         continue;
1475
1476                 if (cfg->verbose_level > 3) mono_print_bb (bb, "BEFORE DECOMPOSE-ARRAY-ACCESS-OPTS ");
1477
1478                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1479                 restart = TRUE;
1480
1481                 while (restart) {
1482                         restart = FALSE;
1483
1484                         for (ins = bb->code; ins; ins = ins->next) {
1485                                 switch (ins->opcode) {
1486                                 case OP_LDLEN:
1487                                         NEW_LOAD_MEMBASE_FLAGS (cfg, dest, OP_LOADI4_MEMBASE, ins->dreg, ins->sreg1,
1488                                                                                         G_STRUCT_OFFSET (MonoArray, max_length), ins->flags | MONO_INST_INVARIANT_LOAD);
1489                                         MONO_ADD_INS (cfg->cbb, dest);
1490                                         break;
1491                                 case OP_BOUNDS_CHECK:
1492                                         MONO_EMIT_NULL_CHECK (cfg, ins->sreg1);
1493                                         if (COMPILE_LLVM (cfg))
1494                                                 MONO_EMIT_DEFAULT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2, ins->flags & MONO_INST_FAULT);
1495                                         else
1496                                                 MONO_ARCH_EMIT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2);
1497                                         break;
1498                                 case OP_NEWARR:
1499                                         if (cfg->opt & MONO_OPT_SHARED) {
1500                                                 EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
1501                                                 EMIT_NEW_CLASSCONST (cfg, iargs [1], ins->inst_newa_class);
1502                                                 MONO_INST_NEW (cfg, iargs [2], OP_MOVE);
1503                                                 iargs [2]->dreg = ins->sreg1;
1504
1505                                                 dest = mono_emit_jit_icall (cfg, mono_array_new, iargs);
1506                                                 dest->dreg = ins->dreg;
1507                                         } else {
1508                                                 MonoClass *array_class = mono_array_class_get (ins->inst_newa_class, 1);
1509                                                 MonoVTable *vtable = mono_class_vtable (cfg->domain, array_class);
1510                                                 MonoMethod *managed_alloc = mono_gc_get_managed_array_allocator (array_class);
1511
1512                                                 g_assert (vtable); /*This shall not fail since we check for this condition on OP_NEWARR creation*/
1513                                                 NEW_VTABLECONST (cfg, iargs [0], vtable);
1514                                                 MONO_ADD_INS (cfg->cbb, iargs [0]);
1515                                                 MONO_INST_NEW (cfg, iargs [1], OP_MOVE);
1516                                                 iargs [1]->dreg = ins->sreg1;
1517
1518                                                 if (managed_alloc)
1519                                                         dest = mono_emit_method_call (cfg, managed_alloc, iargs, NULL);
1520                                                 else
1521                                                         dest = mono_emit_jit_icall (cfg, mono_array_new_specific, iargs);
1522                                                 dest->dreg = ins->dreg;
1523                                         }
1524                                         break;
1525                                 case OP_STRLEN:
1526                                         MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS (cfg, OP_LOADI4_MEMBASE, ins->dreg,
1527                                                                                                                  ins->sreg1, G_STRUCT_OFFSET (MonoString, length), ins->flags | MONO_INST_INVARIANT_LOAD);
1528                                         break;
1529                                 default:
1530                                         break;
1531                                 }
1532
1533                                 g_assert (cfg->cbb == first_bb);
1534
1535                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1536                                         /* Replace the original instruction with the new code sequence */
1537
1538                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1539                                         first_bb->code = first_bb->last_ins = NULL;
1540                                         first_bb->in_count = first_bb->out_count = 0;
1541                                         cfg->cbb = first_bb;
1542                                 }
1543                                 else
1544                                         prev = ins;
1545                         }
1546                 }
1547
1548                 if (cfg->verbose_level > 3) mono_print_bb (bb, "AFTER DECOMPOSE-ARRAY-ACCESS-OPTS ");
1549         }
1550 }
1551
1552 typedef union {
1553         guint32 vali [2];
1554         gint64 vall;
1555         double vald;
1556 } DVal;
1557
1558 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
1559
1560 /**
1561  * mono_decompose_soft_float:
1562  *
1563  *  Soft float support on ARM. We store each double value in a pair of integer vregs,
1564  * similar to long support on 32 bit platforms. 32 bit float values require special
1565  * handling when used as locals, arguments, and in calls.
1566  * One big problem with soft-float is that there are few r4 test cases in our test suite.
1567  */
1568 void
1569 mono_decompose_soft_float (MonoCompile *cfg)
1570 {
1571         MonoBasicBlock *bb, *first_bb;
1572
1573         /*
1574          * This pass creates long opcodes, so it should be run before decompose_long_opts ().
1575          */
1576
1577         /**
1578          * Create a dummy bblock and emit code into it so we can use the normal 
1579          * code generation macros.
1580          */
1581         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1582         first_bb = cfg->cbb;
1583
1584         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1585                 MonoInst *ins;
1586                 MonoInst *prev = NULL;
1587                 gboolean restart;
1588
1589                 if (cfg->verbose_level > 3) mono_print_bb (bb, "BEFORE HANDLE-SOFT-FLOAT ");
1590
1591                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1592                 restart = TRUE;
1593
1594                 while (restart) {
1595                         restart = FALSE;
1596
1597                         for (ins = bb->code; ins; ins = ins->next) {
1598                                 const char *spec = INS_INFO (ins->opcode);
1599
1600                                 /* Most fp operations are handled automatically by opcode emulation */
1601
1602                                 switch (ins->opcode) {
1603                                 case OP_R8CONST: {
1604                                         DVal d;
1605                                         d.vald = *(double*)ins->inst_p0;
1606                                         MONO_EMIT_NEW_I8CONST (cfg, ins->dreg, d.vall);
1607                                         break;
1608                                 }
1609                                 case OP_R4CONST: {
1610                                         DVal d;
1611                                         /* We load the r8 value */
1612                                         d.vald = *(float*)ins->inst_p0;
1613                                         MONO_EMIT_NEW_I8CONST (cfg, ins->dreg, d.vall);
1614                                         break;
1615                                 }
1616                                 case OP_FMOVE:
1617                                         ins->opcode = OP_LMOVE;
1618                                         break;
1619                                 case OP_FGETLOW32:
1620                                         ins->opcode = OP_MOVE;
1621                                         ins->sreg1 = ins->sreg1 + 1;
1622                                         break;
1623                                 case OP_FGETHIGH32:
1624                                         ins->opcode = OP_MOVE;
1625                                         ins->sreg1 = ins->sreg1 + 2;
1626                                         break;
1627                                 case OP_SETFRET: {
1628                                         int reg = ins->sreg1;
1629
1630                                         ins->opcode = OP_SETLRET;
1631                                         ins->dreg = -1;
1632                                         ins->sreg1 = reg + 1;
1633                                         ins->sreg2 = reg + 2;
1634                                         break;
1635                                 }
1636                                 case OP_LOADR8_MEMBASE:
1637                                         ins->opcode = OP_LOADI8_MEMBASE;
1638                                         break;
1639                                 case OP_STORER8_MEMBASE_REG:
1640                                         ins->opcode = OP_STOREI8_MEMBASE_REG;
1641                                         break;
1642                                 case OP_STORER4_MEMBASE_REG: {
1643                                         MonoInst *iargs [2];
1644                                         int addr_reg;
1645
1646                                         /* Arg 1 is the double value */
1647                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1648                                         iargs [0]->dreg = ins->sreg1;
1649
1650                                         /* Arg 2 is the address to store to */
1651                                         addr_reg = mono_alloc_preg (cfg);
1652                                         EMIT_NEW_BIALU_IMM (cfg, iargs [1], OP_PADD_IMM, addr_reg, ins->inst_destbasereg, ins->inst_offset);
1653                                         mono_emit_jit_icall (cfg, mono_fstore_r4, iargs);
1654                                         restart = TRUE;
1655                                         break;
1656                                 }
1657                                 case OP_LOADR4_MEMBASE: {
1658                                         MonoInst *iargs [1];
1659                                         MonoInst *conv;
1660                                         int addr_reg;
1661
1662                                         addr_reg = mono_alloc_preg (cfg);
1663                                         EMIT_NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, addr_reg, ins->inst_basereg, ins->inst_offset);
1664                                         conv = mono_emit_jit_icall (cfg, mono_fload_r4, iargs);
1665                                         conv->dreg = ins->dreg;
1666                                         break;
1667                                 }                                       
1668                                 case OP_FCALL:
1669                                 case OP_FCALL_REG:
1670                                 case OP_FCALL_MEMBASE: {
1671                                         MonoCallInst *call = (MonoCallInst*)ins;
1672                                         if (call->signature->ret->type == MONO_TYPE_R4) {
1673                                                 MonoCallInst *call2;
1674                                                 MonoInst *iargs [1];
1675                                                 MonoInst *conv;
1676                                                 GSList *l;
1677
1678                                                 /* Convert the call into a call returning an int */
1679                                                 MONO_INST_NEW_CALL (cfg, call2, OP_CALL);
1680                                                 memcpy (call2, call, sizeof (MonoCallInst));
1681                                                 switch (ins->opcode) {
1682                                                 case OP_FCALL:
1683                                                         call2->inst.opcode = OP_CALL;
1684                                                         break;
1685                                                 case OP_FCALL_REG:
1686                                                         call2->inst.opcode = OP_CALL_REG;
1687                                                         break;
1688                                                 case OP_FCALL_MEMBASE:
1689                                                         call2->inst.opcode = OP_CALL_MEMBASE;
1690                                                         break;
1691                                                 default:
1692                                                         g_assert_not_reached ();
1693                                                 }
1694                                                 call2->inst.dreg = mono_alloc_ireg (cfg);
1695                                                 MONO_ADD_INS (cfg->cbb, (MonoInst*)call2);
1696
1697                                                 /* Remap OUTARG_VT instructions referencing this call */
1698                                                 for (l = call->outarg_vts; l; l = l->next)
1699                                                         ((MonoInst*)(l->data))->inst_p0 = call2;
1700
1701                                                 /* FIXME: Optimize this */
1702
1703                                                 /* Emit an r4->r8 conversion */
1704                                                 EMIT_NEW_VARLOADA_VREG (cfg, iargs [0], call2->inst.dreg, &mono_defaults.int32_class->byval_arg);
1705                                                 conv = mono_emit_jit_icall (cfg, mono_fload_r4, iargs);
1706                                                 conv->dreg = ins->dreg;
1707
1708                                                 /* The call sequence might include fp ins */
1709                                                 restart = TRUE;
1710                                         } else {
1711                                                 switch (ins->opcode) {
1712                                                 case OP_FCALL:
1713                                                         ins->opcode = OP_LCALL;
1714                                                         break;
1715                                                 case OP_FCALL_REG:
1716                                                         ins->opcode = OP_LCALL_REG;
1717                                                         break;
1718                                                 case OP_FCALL_MEMBASE:
1719                                                         ins->opcode = OP_LCALL_MEMBASE;
1720                                                         break;
1721                                                 default:
1722                                                         g_assert_not_reached ();
1723                                                 }
1724                                         }
1725                                         break;
1726                                 }
1727                                 case OP_FCOMPARE: {
1728                                         MonoJitICallInfo *info;
1729                                         MonoInst *iargs [2];
1730                                         MonoInst *call, *cmp, *br;
1731
1732                                         /* Convert fcompare+fbcc to icall+icompare+beq */
1733
1734                                         if (!ins->next) {
1735                                                 /* The branch might be optimized away */
1736                                                 NULLIFY_INS (ins);
1737                                                 break;
1738                                         }
1739
1740                                         info = mono_find_jit_opcode_emulation (ins->next->opcode);
1741                                         if (!info) {
1742                                                 /* The branch might be optimized away */
1743                                                 NULLIFY_INS (ins);
1744                                                 break;
1745                                         }
1746
1747                                         /* Create dummy MonoInst's for the arguments */
1748                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1749                                         iargs [0]->dreg = ins->sreg1;
1750                                         MONO_INST_NEW (cfg, iargs [1], OP_ARG);
1751                                         iargs [1]->dreg = ins->sreg2;
1752
1753                                         call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, iargs);
1754
1755                                         MONO_INST_NEW (cfg, cmp, OP_ICOMPARE_IMM);
1756                                         cmp->sreg1 = call->dreg;
1757                                         cmp->inst_imm = 0;
1758                                         MONO_ADD_INS (cfg->cbb, cmp);
1759                                         
1760                                         MONO_INST_NEW (cfg, br, OP_IBNE_UN);
1761                                         br->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof (gpointer) * 2);
1762                                         br->inst_true_bb = ins->next->inst_true_bb;
1763                                         br->inst_false_bb = ins->next->inst_false_bb;
1764                                         MONO_ADD_INS (cfg->cbb, br);
1765
1766                                         /* The call sequence might include fp ins */
1767                                         restart = TRUE;
1768
1769                                         /* Skip fbcc or fccc */
1770                                         NULLIFY_INS (ins->next);
1771                                         break;
1772                                 }
1773                                 case OP_FCEQ:
1774                                 case OP_FCGT:
1775                                 case OP_FCGT_UN:
1776                                 case OP_FCLT:
1777                                 case OP_FCLT_UN: {
1778                                         MonoJitICallInfo *info;
1779                                         MonoInst *iargs [2];
1780                                         MonoInst *call;
1781
1782                                         /* Convert fccc to icall+icompare+iceq */
1783
1784                                         info = mono_find_jit_opcode_emulation (ins->opcode);
1785                                         g_assert (info);
1786
1787                                         /* Create dummy MonoInst's for the arguments */
1788                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1789                                         iargs [0]->dreg = ins->sreg1;
1790                                         MONO_INST_NEW (cfg, iargs [1], OP_ARG);
1791                                         iargs [1]->dreg = ins->sreg2;
1792
1793                                         call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, iargs);
1794
1795                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, call->dreg, 1);
1796                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, ins->dreg, -1);
1797
1798                                         /* The call sequence might include fp ins */
1799                                         restart = TRUE;
1800                                         break;
1801                                 }
1802                                 case OP_CKFINITE: {
1803                                         MonoInst *iargs [2];
1804                                         MonoInst *call, *cmp;
1805
1806                                         /* Convert to icall+icompare+cond_exc+move */
1807
1808                                         /* Create dummy MonoInst's for the arguments */
1809                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1810                                         iargs [0]->dreg = ins->sreg1;
1811
1812                                         call = mono_emit_jit_icall (cfg, mono_isfinite, iargs);
1813
1814                                         MONO_INST_NEW (cfg, cmp, OP_ICOMPARE_IMM);
1815                                         cmp->sreg1 = call->dreg;
1816                                         cmp->inst_imm = 1;
1817                                         MONO_ADD_INS (cfg->cbb, cmp);
1818
1819                                         MONO_EMIT_NEW_COND_EXC (cfg, INE_UN, "ArithmeticException");
1820
1821                                         /* Do the assignment if the value is finite */
1822                                         MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, ins->dreg, ins->sreg1);
1823
1824                                         restart = TRUE;
1825                                         break;
1826                                 }
1827                                 default:
1828                                         if (spec [MONO_INST_SRC1] == 'f' || spec [MONO_INST_SRC2] == 'f' || spec [MONO_INST_DEST] == 'f') {
1829                                                 mono_print_ins (ins);
1830                                                 g_assert_not_reached ();
1831                                         }
1832                                         break;
1833                                 }
1834
1835                                 g_assert (cfg->cbb == first_bb);
1836
1837                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1838                                         /* Replace the original instruction with the new code sequence */
1839
1840                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1841                                         first_bb->code = first_bb->last_ins = NULL;
1842                                         first_bb->in_count = first_bb->out_count = 0;
1843                                         cfg->cbb = first_bb;
1844                                 }
1845                                 else
1846                                         prev = ins;
1847                         }
1848                 }
1849
1850                 if (cfg->verbose_level > 3) mono_print_bb (bb, "AFTER HANDLE-SOFT-FLOAT ");
1851         }
1852
1853         mono_decompose_long_opts (cfg);
1854 }
1855
1856 #endif
1857
1858 #endif /* DISABLE_JIT */