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