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