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