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