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