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