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