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