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