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