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