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