Remove excessive shortcut key matching in ToolStrip
[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)
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, "DivideByZeroException");
470                         }
471 #endif
472                         MONO_EMIT_NEW_BIALU (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->sreg2);
473                         ins->opcode = OP_NOP;
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                 } else if ((ins->inst_imm > 0) && (ins->inst_imm < (1LL << 32)) && (power != -1)) {
490                         gboolean is_long = ins->opcode == OP_LREM_IMM;
491                         int compensator_reg = alloc_ireg (cfg);
492                         int intermediate_reg;
493
494                         /* Based on gcc code */
495
496                         /* Add compensation for negative numerators */
497
498                         if (power > 1) {
499                                 intermediate_reg = compensator_reg;
500                                 MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_SHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31);
501                         } else {
502                                 intermediate_reg = ins->sreg1;
503                         }
504
505                         MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_SHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power);
506                         MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LADD : OP_IADD, ins->dreg, ins->sreg1, compensator_reg);
507                         /* Compute remainder */
508                         MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LAND_IMM : OP_AND_IMM, ins->dreg, ins->dreg, (1 << power) - 1);
509                         /* Remove compensation */
510                         MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LSUB : OP_ISUB, ins->dreg, ins->dreg, compensator_reg);
511
512                         NULLIFY_INS (ins);
513                 }
514                 break;
515         }
516
517         default:
518                 emulate = TRUE;
519                 break;
520         }
521
522         if (emulate) {
523                 MonoJitICallInfo *info = NULL;
524
525 #if SIZEOF_REGISTER == 8
526                 if (decompose_long_opcode (cfg, ins, &repl))
527                         emulate = FALSE;
528 #else
529                 if (COMPILE_LLVM (cfg) && decompose_long_opcode (cfg, ins, &repl))
530                         emulate = FALSE;
531 #endif
532
533                 if (emulate)
534                         info = mono_find_jit_opcode_emulation (ins->opcode);
535                 if (info) {
536                         MonoInst **args;
537                         MonoInst *call;
538
539                         /* Create dummy MonoInst's for the arguments */
540                         g_assert (!info->sig->hasthis);
541                         g_assert (info->sig->param_count <= MONO_MAX_SRC_REGS);
542
543                         args = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * info->sig->param_count);
544                         if (info->sig->param_count > 0) {
545                                 int sregs [MONO_MAX_SRC_REGS];
546                                 int num_sregs, i;
547                                 num_sregs = mono_inst_get_src_registers (ins, sregs);
548                                 g_assert (num_sregs == info->sig->param_count);
549                                 for (i = 0; i < num_sregs; ++i) {
550                                         MONO_INST_NEW (cfg, args [i], OP_ARG);
551                                         args [i]->dreg = sregs [i];
552                                 }
553                         }
554
555                         call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, args);
556                         call->dreg = ins->dreg;
557
558                         NULLIFY_INS (ins);
559                 }
560         }
561
562         if (ins->opcode == OP_NOP) {
563                 if (repl) {
564                         repl->type = type;
565                         return repl;
566                 } else {
567                         /* Use the last emitted instruction */
568                         ins = cfg->cbb->last_ins;
569                         g_assert (ins);
570                         ins->type = type;
571                         g_assert (ins->dreg == dreg);
572                         return ins;
573                 }
574         } else {
575                 return ins;
576         }
577 }
578
579 #if SIZEOF_REGISTER == 4
580 static int lbr_decomp [][2] = {
581         {0, 0}, /* BEQ */
582         {OP_IBGT, OP_IBGE_UN}, /* BGE */
583         {OP_IBGT, OP_IBGT_UN}, /* BGT */
584         {OP_IBLT, OP_IBLE_UN}, /* BLE */
585         {OP_IBLT, OP_IBLT_UN}, /* BLT */
586         {0, 0}, /* BNE_UN */
587         {OP_IBGT_UN, OP_IBGE_UN}, /* BGE_UN */
588         {OP_IBGT_UN, OP_IBGT_UN}, /* BGT_UN */
589         {OP_IBLT_UN, OP_IBLE_UN}, /* BLE_UN */
590         {OP_IBLT_UN, OP_IBLT_UN}, /* BLT_UN */
591 };
592
593 static int lcset_decomp [][2] = {
594         {0, 0}, /* CEQ */
595         {OP_IBLT, OP_IBLE_UN}, /* CGT */
596         {OP_IBLT_UN, OP_IBLE_UN}, /* CGT_UN */
597         {OP_IBGT, OP_IBGE_UN}, /* CLT */
598         {OP_IBGT_UN, OP_IBGE_UN}, /* CLT_UN */
599 };
600 #endif
601
602 /**
603  * mono_decompose_long_opts:
604  *
605  *  Decompose 64bit opcodes into 32bit opcodes on 32 bit platforms.
606  */
607 void
608 mono_decompose_long_opts (MonoCompile *cfg)
609 {
610 #if SIZEOF_REGISTER == 4
611         MonoBasicBlock *bb, *first_bb;
612
613         /*
614          * Some opcodes, like lcall can't be decomposed so the rest of the JIT
615          * needs to be able to handle long vregs.
616          */
617
618         /* reg + 1 contains the ls word, reg + 2 contains the ms word */
619
620         /**
621          * Create a dummy bblock and emit code into it so we can use the normal 
622          * code generation macros.
623          */
624         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
625         first_bb = cfg->cbb;
626
627         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
628                 MonoInst *tree = bb->code;      
629                 MonoInst *prev = NULL;
630
631                    /*
632                 mono_print_bb (bb, "BEFORE LOWER_LONG_OPTS");
633                 */
634
635                 tree = bb->code;
636                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
637
638                 while (tree) {
639
640 #ifdef MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS
641                         mono_arch_decompose_long_opts (cfg, tree);
642 #endif
643
644                         switch (tree->opcode) {
645                         case OP_I8CONST:
646                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 1, tree->inst_ls_word);
647                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, tree->inst_ms_word);
648                                 break;
649                         case OP_DUMMY_I8CONST:
650                                 MONO_EMIT_NEW_DUMMY_INIT (cfg, tree->dreg + 1, OP_DUMMY_ICONST);
651                                 MONO_EMIT_NEW_DUMMY_INIT (cfg, tree->dreg + 2, OP_DUMMY_ICONST);
652                                 break;
653                         case OP_LMOVE:
654                         case OP_LCONV_TO_U8:
655                         case OP_LCONV_TO_I8:
656                         case OP_LCONV_TO_OVF_U8_UN:
657                         case OP_LCONV_TO_OVF_I8:
658                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1);
659                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2);
660                                 break;
661                         case OP_STOREI8_MEMBASE_REG:
662                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_MS_WORD_OFFSET, tree->sreg1 + 2);
663                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_LS_WORD_OFFSET, tree->sreg1 + 1);
664                                 break;
665                         case OP_LOADI8_MEMBASE:
666                                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tree->dreg + 2, tree->inst_basereg, tree->inst_offset + MINI_MS_WORD_OFFSET);
667                                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tree->dreg + 1, tree->inst_basereg, tree->inst_offset + MINI_LS_WORD_OFFSET);
668                                 break;
669
670                         case OP_ICONV_TO_I8: {
671                                 guint32 tmpreg = alloc_ireg (cfg);
672
673                                 /* branchless code:
674                                  * low = reg;
675                                  * tmp = low > -1 ? 1: 0;
676                                  * high = tmp - 1; if low is zero or pos high becomes 0, else -1
677                                  */
678                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
679                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, tree->dreg + 1, -1);
680                                 MONO_EMIT_NEW_BIALU (cfg, OP_ICGT, tmpreg, -1, -1);
681                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISUB_IMM, tree->dreg + 2, tmpreg, 1);
682                                 break;
683                         }
684                         case OP_ICONV_TO_U8:
685                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
686                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
687                                 break;
688                         case OP_ICONV_TO_OVF_I8:
689                                 /* a signed 32 bit num always fits in a signed 64 bit one */
690                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, tree->dreg + 2, tree->sreg1, 31);
691                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
692                                 break;
693                         case OP_ICONV_TO_OVF_U8:
694                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1, 0);
695                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
696                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
697                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
698                                 break;
699                         case OP_ICONV_TO_OVF_I8_UN:
700                         case OP_ICONV_TO_OVF_U8_UN:
701                                 /* an unsigned 32 bit num always fits in an (un)signed 64 bit one */
702                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
703                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
704                                 break;
705                         case OP_LCONV_TO_I1:
706                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1);
707                                 break;
708                         case OP_LCONV_TO_U1:
709                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U1, tree->dreg, tree->sreg1 + 1);
710                                 break;
711                         case OP_LCONV_TO_I2:
712                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1);
713                                 break;
714                         case OP_LCONV_TO_U2:
715                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U2, tree->dreg, tree->sreg1 + 1);
716                                 break;
717                         case OP_LCONV_TO_I4:
718                         case OP_LCONV_TO_U4:
719                         case OP_LCONV_TO_I:
720                         case OP_LCONV_TO_U:
721                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1);
722                                 break;
723                         case OP_LCONV_TO_R8:
724                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R8_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
725                                 break;
726                         case OP_LCONV_TO_R4:
727                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R4_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
728                                 break;
729                         case OP_LCONV_TO_R_UN:
730                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R_UN_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
731                                 break;
732                         case OP_LCONV_TO_OVF_I1: {
733                                 MonoBasicBlock *is_negative, *end_label;
734
735                                 NEW_BBLOCK (cfg, is_negative);
736                                 NEW_BBLOCK (cfg, end_label);
737
738                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
739                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
740                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, -1);
741                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
742
743                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
744                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative);
745
746                                 /* Positive */
747                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 127);
748                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
749                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label);
750
751                                 /* Negative */
752                                 MONO_START_BB (cfg, is_negative);
753                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -128);
754                                 MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException");
755
756                                 MONO_START_BB (cfg, end_label);
757
758                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1);
759                                 break;
760                         }
761                         case OP_LCONV_TO_OVF_I1_UN:
762                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
763                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
764
765                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 127);
766                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
767                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -128);
768                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
769                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1);
770                                 break;
771                         case OP_LCONV_TO_OVF_U1:
772                         case OP_LCONV_TO_OVF_U1_UN:
773                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
774                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
775
776                                 /* probe value to be within 0 to 255 */
777                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 255);
778                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
779                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, tree->sreg1 + 1, 0xff);
780                                 break;
781                         case OP_LCONV_TO_OVF_I2: {
782                                 MonoBasicBlock *is_negative, *end_label;
783
784                                 NEW_BBLOCK (cfg, is_negative);
785                                 NEW_BBLOCK (cfg, end_label);
786
787                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
788                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
789                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, -1);
790                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
791
792                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
793                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative);
794
795                                 /* Positive */
796                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 32767);
797                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
798                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label);
799
800                                 /* Negative */
801                                 MONO_START_BB (cfg, is_negative);
802                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -32768);
803                                 MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException");
804                                 MONO_START_BB (cfg, end_label);
805
806                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1);
807                                 break;
808                         }
809                         case OP_LCONV_TO_OVF_I2_UN:
810                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
811                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
812
813                                 /* Probe value to be within -32768 and 32767 */
814                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 32767);
815                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
816                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -32768);
817                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
818                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1);
819                                 break;
820                         case OP_LCONV_TO_OVF_U2:
821                         case OP_LCONV_TO_OVF_U2_UN:
822                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
823                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
824
825                                 /* Probe value to be within 0 and 65535 */
826                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 0xffff);
827                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
828                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, tree->sreg1 + 1, 0xffff);
829                                 break;
830                         case OP_LCONV_TO_OVF_I4:
831                         case OP_LCONV_TO_OVF_I:
832                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_OVF_I4_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
833                                 break;
834                         case OP_LCONV_TO_OVF_U4:
835                         case OP_LCONV_TO_OVF_U:
836                         case OP_LCONV_TO_OVF_U4_UN:
837                         case OP_LCONV_TO_OVF_U_UN:
838                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
839                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
840                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1);
841                                 break;
842                         case OP_LCONV_TO_OVF_I_UN:
843                         case OP_LCONV_TO_OVF_I4_UN:
844                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
845                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
846                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 1, 0);
847                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
848                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1);
849                                 break;
850                         case OP_LCONV_TO_OVF_U8:
851                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
852                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
853
854                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1);
855                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2);
856                                 break;
857                         case OP_LCONV_TO_OVF_I8_UN:
858                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
859                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
860
861                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1);
862                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2);
863                                 break;
864
865                         case OP_LADD:
866                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
867                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
868                                 break;
869                         case OP_LSUB:
870                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
871                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
872                                 break;
873
874                         case OP_LADD_OVF:
875                                 /* ADC sets the condition code */
876                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
877                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
878                                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
879                                 break;
880                         case OP_LADD_OVF_UN:
881                                 /* ADC sets the condition code */
882                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
883                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
884                                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
885                                 break;
886                         case OP_LSUB_OVF:
887                                 /* SBB sets the condition code */
888                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
889                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
890                                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
891                                 break;
892                         case OP_LSUB_OVF_UN:
893                                 /* SBB sets the condition code */
894                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
895                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
896                                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
897                                 break;
898                         case OP_LAND:
899                                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
900                                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
901                                 break;
902                         case OP_LOR:
903                                 MONO_EMIT_NEW_BIALU (cfg, OP_IOR, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
904                                 MONO_EMIT_NEW_BIALU (cfg, OP_IOR, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
905                                 break;
906                         case OP_LXOR:
907                                 MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
908                                 MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
909                                 break;
910                         case OP_LNOT:
911                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 1, tree->sreg1 + 1);
912                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 2, tree->sreg1 + 2);
913                                 break;
914                         case OP_LNEG:
915                                 /* Handled in mono_arch_decompose_long_opts () */
916                                 g_assert_not_reached ();
917                                 break;
918                         case OP_LMUL:
919                                 /* Emulated */
920                                 /* FIXME: Add OP_BIGMUL optimization */
921                                 break;
922
923                         case OP_LADD_IMM:
924                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADDCC_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
925                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
926                                 break;
927                         case OP_LSUB_IMM:
928                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUBCC_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
929                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SBB_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
930                                 break;
931                         case OP_LAND_IMM:
932                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
933                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
934                                 break;
935                         case OP_LOR_IMM:
936                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
937                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
938                                 break;
939                         case OP_LXOR_IMM:
940                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
941                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
942                                 break;
943                         case OP_LSHR_UN_IMM:
944                                 if (tree->inst_c1 == 32) {
945
946                                         /* The original code had this comment: */
947                                         /* special case that gives a nice speedup and happens to workaorund a ppc jit but (for the release)
948                                          * later apply the speedup to the left shift as well
949                                          * See BUG# 57957.
950                                          */
951                                         /* FIXME: Move this to the strength reduction pass */
952                                         /* just move the upper half to the lower and zero the high word */
953                                         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 2);
954                                         MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
955                                 }
956                                 break;
957                         case OP_LSHL_IMM:
958                                 if (tree->inst_c1 == 32) {
959                                         /* just move the lower half to the upper and zero the lower word */
960                                         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 1);
961                                         MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 1, 0);
962                                 }
963                                 break;
964
965                         case OP_LCOMPARE: {
966                                 MonoInst *next = tree->next;
967
968                                 g_assert (next);
969
970                                 switch (next->opcode) {
971                                 case OP_LBEQ:
972                                 case OP_LBNE_UN: {
973                                         int d1, d2;
974
975                                         /* Branchless version based on gcc code */
976                                         d1 = alloc_ireg (cfg);
977                                         d2 = alloc_ireg (cfg);
978                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, tree->sreg1 + 1, tree->sreg2 + 1);
979                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, tree->sreg1 + 2, tree->sreg2 + 2);
980                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
981                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
982                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
983                                         next->opcode = OP_NOP;
984                                         break;
985                                 }
986                                 case OP_LBGE:
987                                 case OP_LBGT:
988                                 case OP_LBLE:
989                                 case OP_LBLT:
990                                 case OP_LBGE_UN:
991                                 case OP_LBGT_UN:
992                                 case OP_LBLE_UN:
993                                 case OP_LBLT_UN:
994                                         /* Convert into three comparisons + branches */
995                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
996                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lbr_decomp [next->opcode - OP_LBEQ][0], next->inst_true_bb);
997                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
998                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
999                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1);
1000                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
1001                                         next->opcode = OP_NOP;
1002                                         break;
1003                                 case OP_LCEQ: {
1004                                         int d1, d2;
1005         
1006                                         /* Branchless version based on gcc code */
1007                                         d1 = alloc_ireg (cfg);
1008                                         d2 = alloc_ireg (cfg);
1009                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, tree->sreg1 + 1, tree->sreg2 + 1);
1010                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, tree->sreg1 + 2, tree->sreg2 + 2);
1011                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
1012
1013                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
1014                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
1015                                         next->opcode = OP_NOP;
1016                                         break;
1017                                 }
1018                                 case OP_LCLT:
1019                                 case OP_LCLT_UN:
1020                                 case OP_LCGT:
1021                                 case OP_LCGT_UN: {
1022                                         MonoBasicBlock *set_to_0, *set_to_1;
1023         
1024                                         NEW_BBLOCK (cfg, set_to_0);
1025                                         NEW_BBLOCK (cfg, set_to_1);
1026
1027                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 0);
1028                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
1029                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][0], set_to_0);
1030                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
1031                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, set_to_1);
1032                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1);
1033                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][1], set_to_0);
1034                                         MONO_START_BB (cfg, set_to_1);
1035                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
1036                                         MONO_START_BB (cfg, set_to_0);
1037                                         next->opcode = OP_NOP;
1038                                         break;  
1039                                 }
1040                                 default:
1041                                         g_assert_not_reached ();
1042                                 }
1043                                 break;
1044                         }
1045
1046                         /* Not yet used, since lcompare is decomposed before local cprop */
1047                         case OP_LCOMPARE_IMM: {
1048                                 MonoInst *next = tree->next;
1049                                 guint32 low_imm = tree->inst_ls_word;
1050                                 guint32 high_imm = tree->inst_ms_word;
1051                                 int low_reg = tree->sreg1 + 1;
1052                                 int high_reg = tree->sreg1 + 2;
1053
1054                                 g_assert (next);
1055
1056                                 switch (next->opcode) {
1057                                 case OP_LBEQ:
1058                                 case OP_LBNE_UN: {
1059                                         int d1, d2;
1060
1061                                         /* Branchless version based on gcc code */
1062                                         d1 = alloc_ireg (cfg);
1063                                         d2 = alloc_ireg (cfg);
1064                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d1, low_reg, low_imm);
1065                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d2, high_reg, high_imm);
1066                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
1067                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
1068                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
1069                                         next->opcode = OP_NOP;
1070                                         break;
1071                                 }
1072
1073                                 case OP_LBGE:
1074                                 case OP_LBGT:
1075                                 case OP_LBLE:
1076                                 case OP_LBLT:
1077                                 case OP_LBGE_UN:
1078                                 case OP_LBGT_UN:
1079                                 case OP_LBLE_UN:
1080                                 case OP_LBLT_UN:
1081                                         /* Convert into three comparisons + branches */
1082                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1083                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lbr_decomp [next->opcode - OP_LBEQ][0], next->inst_true_bb);
1084                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1085                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
1086                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
1087                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
1088                                         next->opcode = OP_NOP;
1089                                         break;
1090                                 case OP_LCEQ: {
1091                                         int d1, d2;
1092         
1093                                         /* Branchless version based on gcc code */
1094                                         d1 = alloc_ireg (cfg);
1095                                         d2 = alloc_ireg (cfg);
1096                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d1, low_reg, low_imm);
1097                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d2, high_reg, high_imm);
1098                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
1099
1100                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
1101                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
1102                                         next->opcode = OP_NOP;
1103                                         break;
1104                                 }
1105                                 case OP_LCLT:
1106                                 case OP_LCLT_UN:
1107                                 case OP_LCGT:
1108                                 case OP_LCGT_UN: {
1109                                         MonoBasicBlock *set_to_0, *set_to_1;
1110         
1111                                         NEW_BBLOCK (cfg, set_to_0);
1112                                         NEW_BBLOCK (cfg, set_to_1);
1113
1114                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 0);
1115                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1116                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][0], set_to_0);
1117                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1118                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, set_to_1);
1119                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
1120                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][1], set_to_0);
1121                                         MONO_START_BB (cfg, set_to_1);
1122                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
1123                                         MONO_START_BB (cfg, set_to_0);
1124                                         next->opcode = OP_NOP;
1125                                         break;  
1126                                 }
1127                                 default:
1128                                         g_assert_not_reached ();
1129                                 }
1130                                 break;
1131                         }
1132
1133                         default:
1134                                 break;
1135                         }
1136
1137                         if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1138                                 MonoInst *new_prev;
1139
1140                                 /* Replace the original instruction with the new code sequence */
1141
1142                                 /* Ignore the new value of prev */
1143                                 new_prev = prev;
1144                                 mono_replace_ins (cfg, bb, tree, &new_prev, first_bb, cfg->cbb);
1145
1146                                 /* Process the newly added ops again since they can be long ops too */
1147                                 if (prev)
1148                                         tree = prev->next;
1149                                 else
1150                                         tree = bb->code;
1151
1152                                 first_bb->code = first_bb->last_ins = NULL;
1153                                 first_bb->in_count = first_bb->out_count = 0;
1154                                 cfg->cbb = first_bb;
1155                         }
1156                         else {
1157                                 prev = tree;
1158                                 tree = tree->next;
1159                         }
1160                 }
1161         }
1162 #endif
1163
1164         /*
1165         for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
1166                 mono_print_bb (bb, "AFTER LOWER-LONG-OPTS");
1167         */
1168 }
1169
1170 /**
1171  * mono_decompose_vtype_opts:
1172  *
1173  *  Decompose valuetype opcodes.
1174  */
1175 void
1176 mono_decompose_vtype_opts (MonoCompile *cfg)
1177 {
1178         MonoBasicBlock *bb, *first_bb;
1179
1180         /**
1181          * Using OP_V opcodes and decomposing them later have two main benefits:
1182          * - it simplifies method_to_ir () since there is no need to special-case vtypes
1183          *   everywhere.
1184          * - it gets rid of the LDADDR opcodes generated when vtype operations are decomposed,
1185          *   enabling optimizations to work on vtypes too.
1186          * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it 
1187          * can be executed anytime. It should be executed as late as possible so vtype
1188          * opcodes can be optimized by the other passes.
1189          * The pinvoke wrappers need to manipulate vtypes in their unmanaged representation.
1190          * This is indicated by setting the 'backend.is_pinvoke' field of the MonoInst for the 
1191          * var to 1.
1192          * This is done on demand, ie. by the LDNATIVEOBJ opcode, and propagated by this pass 
1193          * when OP_VMOVE opcodes are decomposed.
1194          */
1195
1196         /* 
1197          * Vregs have no associated type information, so we store the type of the vregs
1198          * in ins->klass.
1199          */
1200
1201         /**
1202          * Create a dummy bblock and emit code into it so we can use the normal 
1203          * code generation macros.
1204          */
1205         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1206         first_bb = cfg->cbb;
1207
1208         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1209                 MonoInst *ins;
1210                 MonoInst *prev = NULL;
1211                 MonoInst *src_var, *dest_var, *src, *dest;
1212                 gboolean restart;
1213                 int dreg;
1214
1215                 if (cfg->verbose_level > 2) mono_print_bb (bb, "BEFORE LOWER-VTYPE-OPTS ");
1216
1217                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1218                 restart = TRUE;
1219
1220                 while (restart) {
1221                         restart = FALSE;
1222
1223                         for (ins = bb->code; ins; ins = ins->next) {
1224                                 switch (ins->opcode) {
1225                                 case OP_VMOVE: {
1226                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1227                                         dest_var = get_vreg_to_inst (cfg, ins->dreg);
1228
1229                                         g_assert (ins->klass);
1230
1231                                         if (!src_var)
1232                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1233
1234                                         if (!dest_var)
1235                                                 dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1236
1237                                         // FIXME:
1238                                         if (src_var->backend.is_pinvoke)
1239                                                 dest_var->backend.is_pinvoke = 1;
1240
1241                                         EMIT_NEW_VARLOADA ((cfg), (src), src_var, src_var->inst_vtype);
1242                                         EMIT_NEW_VARLOADA ((cfg), (dest), dest_var, dest_var->inst_vtype);
1243
1244                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1245                                         break;
1246                                 }
1247                                 case OP_VZERO:
1248                                         g_assert (ins->klass);
1249
1250                                         EMIT_NEW_VARLOADA_VREG (cfg, dest, ins->dreg, &ins->klass->byval_arg);
1251                                         mini_emit_initobj (cfg, dest, NULL, ins->klass);
1252                                         
1253                                         if (cfg->compute_gc_maps) {
1254                                                 MonoInst *tmp;
1255
1256                                                 /* 
1257                                                  * Tell the GC map code that the vtype is considered live after
1258                                                  * the initialization.
1259                                                  */
1260                                                 MONO_INST_NEW (cfg, tmp, OP_GC_LIVENESS_DEF);
1261                                                 tmp->inst_c1 = ins->dreg;
1262                                                 MONO_ADD_INS (cfg->cbb, tmp);
1263                                         }
1264                                         break;
1265                                 case OP_DUMMY_VZERO:
1266                                         NULLIFY_INS (ins);
1267                                         break;
1268                                 case OP_STOREV_MEMBASE: {
1269                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1270
1271                                         if (!src_var) {
1272                                                 g_assert (ins->klass);
1273                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1274                                         }
1275
1276                                         EMIT_NEW_VARLOADA_VREG ((cfg), (src), ins->sreg1, &ins->klass->byval_arg);
1277
1278                                         dreg = alloc_preg (cfg);
1279                                         EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
1280                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1281                                         break;
1282                                 }
1283                                 case OP_LOADV_MEMBASE: {
1284                                         g_assert (ins->klass);
1285
1286                                         dest_var = get_vreg_to_inst (cfg, ins->dreg);
1287                                         // FIXME-VT:
1288                                         // FIXME:
1289                                         if (!dest_var)
1290                                                 dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1291
1292                                         dreg = alloc_preg (cfg);
1293                                         EMIT_NEW_BIALU_IMM (cfg, src, OP_ADD_IMM, dreg, ins->inst_basereg, ins->inst_offset);
1294                                         EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
1295                                         mini_emit_stobj (cfg, dest, src, dest_var->klass, dest_var->backend.is_pinvoke);
1296                                         break;
1297                                 }
1298                                 case OP_OUTARG_VT: {
1299                                         g_assert (ins->klass);
1300
1301                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1302                                         if (!src_var)
1303                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1304                                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
1305
1306                                         mono_arch_emit_outarg_vt (cfg, ins, src);
1307
1308                                         /* This might be decomposed into other vtype opcodes */
1309                                         restart = TRUE;
1310                                         break;
1311                                 }
1312                                 case OP_OUTARG_VTRETADDR: {
1313                                         MonoCallInst *call = (MonoCallInst*)ins->inst_p1;
1314
1315                                         src_var = get_vreg_to_inst (cfg, call->inst.dreg);
1316                                         if (!src_var)
1317                                                 src_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
1318                                         // FIXME: src_var->backend.is_pinvoke ?
1319
1320                                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
1321                                         src->dreg = ins->dreg;
1322                                         break;
1323                                 }
1324                                 case OP_VCALL:
1325                                 case OP_VCALL_REG:
1326                                 case OP_VCALL_MEMBASE: {
1327                                         MonoCallInst *call = (MonoCallInst*)ins;
1328                                         int size;
1329
1330                                         if (call->vret_in_reg) {
1331                                                 MonoCallInst *call2;
1332
1333                                                 /* Replace the vcall with an integer call */
1334                                                 MONO_INST_NEW_CALL (cfg, call2, OP_NOP);
1335                                                 memcpy (call2, call, sizeof (MonoCallInst));
1336                                                 switch (ins->opcode) {
1337                                                 case OP_VCALL:
1338                                                         call2->inst.opcode = OP_CALL;
1339                                                         break;
1340                                                 case OP_VCALL_REG:
1341                                                         call2->inst.opcode = OP_CALL_REG;
1342                                                         break;
1343                                                 case OP_VCALL_MEMBASE:
1344                                                         call2->inst.opcode = OP_CALL_MEMBASE;
1345                                                         break;
1346                                                 }
1347                                                 call2->inst.dreg = alloc_preg (cfg);
1348                                                 MONO_ADD_INS (cfg->cbb, ((MonoInst*)call2));
1349
1350                                                 /* Compute the vtype location */
1351                                                 dest_var = get_vreg_to_inst (cfg, call->inst.dreg);
1352                                                 if (!dest_var)
1353                                                         dest_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
1354                                                 EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
1355
1356                                                 /* Save the result */
1357                                                 if (dest_var->backend.is_pinvoke)
1358                                                         size = mono_class_native_size (mono_class_from_mono_type (dest_var->inst_vtype), NULL);
1359                                                 else
1360                                                         size = mono_type_size (dest_var->inst_vtype, NULL);
1361                                                 switch (size) {
1362                                                 case 1:
1363                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1364                                                         break;
1365                                                 case 2:
1366                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1367                                                         break;
1368                                                 case 3:
1369                                                 case 4:
1370                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1371                                                         break;
1372                                                 case 5:
1373                                                 case 6:
1374                                                 case 7:
1375                                                 case 8:
1376 #if SIZEOF_REGISTER == 4
1377                                                         /*
1378                                                         FIXME Other ABIs might return in different regs than the ones used for LCALL.
1379                                                         FIXME It would be even nicer to be able to leverage the long decompose stuff.
1380                                                         */
1381                                                         switch (call2->inst.opcode) {
1382                                                         case OP_CALL:
1383                                                                 call2->inst.opcode = OP_LCALL;
1384                                                                 break;
1385                                                         case OP_CALL_REG:
1386                                                                 call2->inst.opcode = OP_LCALL_REG;
1387                                                                 break;
1388                                                         case OP_CALL_MEMBASE:
1389                                                                 call2->inst.opcode = OP_LCALL_MEMBASE;
1390                                                                 break;
1391                                                         }
1392                                                         call2->inst.dreg = alloc_lreg (cfg);
1393                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_MS_WORD_OFFSET, call2->inst.dreg + 2);
1394                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_LS_WORD_OFFSET, call2->inst.dreg + 1);
1395 #else
1396                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1397 #endif
1398                                                         break;
1399                                                 default:
1400                                                         /* This assumes the vtype is sizeof (gpointer) long */
1401                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1402                                                         break;
1403                                                 }
1404                                         } else {
1405                                                 switch (ins->opcode) {
1406                                                 case OP_VCALL:
1407                                                         ins->opcode = OP_VCALL2;
1408                                                         break;
1409                                                 case OP_VCALL_REG:
1410                                                         ins->opcode = OP_VCALL2_REG;
1411                                                         break;
1412                                                 case OP_VCALL_MEMBASE:
1413                                                         ins->opcode = OP_VCALL2_MEMBASE;
1414                                                         break;
1415                                                 }
1416                                                 ins->dreg = -1;
1417                                         }
1418                                         break;
1419                                 }
1420                                 default:
1421                                         break;
1422                                 }
1423
1424                                 g_assert (cfg->cbb == first_bb);
1425
1426                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1427                                         /* Replace the original instruction with the new code sequence */
1428
1429                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1430                                         first_bb->code = first_bb->last_ins = NULL;
1431                                         first_bb->in_count = first_bb->out_count = 0;
1432                                         cfg->cbb = first_bb;
1433                                 }
1434                                 else
1435                                         prev = ins;
1436                         }
1437                 }
1438
1439                 if (cfg->verbose_level > 2) mono_print_bb (bb, "AFTER LOWER-VTYPE-OPTS ");
1440         }
1441 }
1442
1443 void
1444 mono_decompose_vtype_opts_llvm (MonoCompile *cfg)
1445 {
1446         MonoBasicBlock *bb, *first_bb;
1447
1448         /* Decompose only the OP_STOREV_MEMBASE opcodes, which need write barriers */
1449
1450         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1451         first_bb = cfg->cbb;
1452
1453         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1454                 MonoInst *ins;
1455                 MonoInst *prev = NULL;
1456                 MonoInst *src_var, *src, *dest;
1457                 gboolean restart;
1458                 int dreg;
1459
1460                 if (cfg->verbose_level > 2) mono_print_bb (bb, "BEFORE LOWER-VTYPE-OPTS(LLVM) ");
1461
1462                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1463                 restart = TRUE;
1464
1465                 while (restart) {
1466                         restart = FALSE;
1467
1468                         for (ins = bb->code; ins; ins = ins->next) {
1469                                 switch (ins->opcode) {
1470                                 case OP_STOREV_MEMBASE: {
1471                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1472
1473                                         if (!src_var) {
1474                                                 g_assert (ins->klass);
1475                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1476                                         }
1477
1478                                         EMIT_NEW_VARLOADA_VREG ((cfg), (src), ins->sreg1, &ins->klass->byval_arg);
1479
1480                                         dreg = alloc_preg (cfg);
1481                                         EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
1482                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1483                                         break;
1484                                 }
1485                                 default:
1486                                         break;
1487                                 }
1488
1489                                 g_assert (cfg->cbb == first_bb);
1490
1491                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1492                                         /* Replace the original instruction with the new code sequence */
1493
1494                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1495                                         first_bb->code = first_bb->last_ins = NULL;
1496                                         first_bb->in_count = first_bb->out_count = 0;
1497                                         cfg->cbb = first_bb;
1498                                 }
1499                                 else
1500                                         prev = ins;
1501                         }
1502                 }
1503
1504                 if (cfg->verbose_level > 2) mono_print_bb (bb, "AFTER LOWER-VTYPE-OPTS(LLVM) ");
1505         }
1506 }
1507
1508 inline static MonoInst *
1509 mono_get_domainvar (MonoCompile *cfg)
1510 {
1511         if (!cfg->domainvar)
1512                 cfg->domainvar = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
1513         return cfg->domainvar;
1514 }
1515
1516 /**
1517  * mono_decompose_array_access_opts:
1518  *
1519  *  Decompose array access opcodes.
1520  */
1521 void
1522 mono_decompose_array_access_opts (MonoCompile *cfg)
1523 {
1524         MonoBasicBlock *bb, *first_bb;
1525
1526         /*
1527          * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it 
1528          * can be executed anytime. It should be run before decompose_long
1529          */
1530
1531         /**
1532          * Create a dummy bblock and emit code into it so we can use the normal 
1533          * code generation macros.
1534          */
1535         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1536         first_bb = cfg->cbb;
1537
1538         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1539                 MonoInst *ins;
1540                 MonoInst *prev = NULL;
1541                 MonoInst *dest;
1542                 MonoInst *iargs [3];
1543                 gboolean restart;
1544
1545                 if (!bb->has_array_access)
1546                         continue;
1547
1548                 if (cfg->verbose_level > 3) mono_print_bb (bb, "BEFORE DECOMPOSE-ARRAY-ACCESS-OPTS ");
1549
1550                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1551                 restart = TRUE;
1552
1553                 while (restart) {
1554                         restart = FALSE;
1555
1556                         for (ins = bb->code; ins; ins = ins->next) {
1557                                 switch (ins->opcode) {
1558                                 case OP_LDLEN:
1559                                         NEW_LOAD_MEMBASE_FLAGS (cfg, dest, OP_LOADI4_MEMBASE, ins->dreg, ins->sreg1,
1560                                                                                         MONO_STRUCT_OFFSET (MonoArray, max_length), ins->flags | MONO_INST_INVARIANT_LOAD);
1561                                         MONO_ADD_INS (cfg->cbb, dest);
1562                                         break;
1563                                 case OP_BOUNDS_CHECK:
1564                                         MONO_EMIT_NULL_CHECK (cfg, ins->sreg1);
1565                                         if (COMPILE_LLVM (cfg))
1566                                                 MONO_EMIT_DEFAULT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2, ins->flags & MONO_INST_FAULT);
1567                                         else
1568                                                 MONO_ARCH_EMIT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2);
1569                                         break;
1570                                 case OP_NEWARR:
1571                                         if (cfg->opt & MONO_OPT_SHARED) {
1572                                                 EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
1573                                                 EMIT_NEW_CLASSCONST (cfg, iargs [1], ins->inst_newa_class);
1574                                                 MONO_INST_NEW (cfg, iargs [2], OP_MOVE);
1575                                                 iargs [2]->dreg = ins->sreg1;
1576
1577                                                 dest = mono_emit_jit_icall (cfg, mono_array_new, iargs);
1578                                                 dest->dreg = ins->dreg;
1579                                         } else {
1580                                                 MonoClass *array_class = mono_array_class_get (ins->inst_newa_class, 1);
1581                                                 MonoVTable *vtable = mono_class_vtable (cfg->domain, array_class);
1582                                                 MonoMethod *managed_alloc = mono_gc_get_managed_array_allocator (array_class);
1583
1584                                                 g_assert (vtable); /*This shall not fail since we check for this condition on OP_NEWARR creation*/
1585                                                 NEW_VTABLECONST (cfg, iargs [0], vtable);
1586                                                 MONO_ADD_INS (cfg->cbb, iargs [0]);
1587                                                 MONO_INST_NEW (cfg, iargs [1], OP_MOVE);
1588                                                 iargs [1]->dreg = ins->sreg1;
1589
1590                                                 if (managed_alloc)
1591                                                         dest = mono_emit_method_call (cfg, managed_alloc, iargs, NULL);
1592                                                 else
1593                                                         dest = mono_emit_jit_icall (cfg, mono_array_new_specific, iargs);
1594                                                 dest->dreg = ins->dreg;
1595                                         }
1596                                         break;
1597                                 case OP_STRLEN:
1598                                         MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS (cfg, OP_LOADI4_MEMBASE, ins->dreg,
1599                                                                                                                  ins->sreg1, MONO_STRUCT_OFFSET (MonoString, length), ins->flags | MONO_INST_INVARIANT_LOAD);
1600                                         break;
1601                                 default:
1602                                         break;
1603                                 }
1604
1605                                 g_assert (cfg->cbb == first_bb);
1606
1607                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1608                                         /* Replace the original instruction with the new code sequence */
1609
1610                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1611                                         first_bb->code = first_bb->last_ins = NULL;
1612                                         first_bb->in_count = first_bb->out_count = 0;
1613                                         cfg->cbb = first_bb;
1614                                 }
1615                                 else
1616                                         prev = ins;
1617                         }
1618                 }
1619
1620                 if (cfg->verbose_level > 3) mono_print_bb (bb, "AFTER DECOMPOSE-ARRAY-ACCESS-OPTS ");
1621         }
1622 }
1623
1624 typedef union {
1625         guint32 vali [2];
1626         gint64 vall;
1627         double vald;
1628 } DVal;
1629
1630 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
1631
1632 /**
1633  * mono_decompose_soft_float:
1634  *
1635  *  Soft float support on ARM. We store each double value in a pair of integer vregs,
1636  * similar to long support on 32 bit platforms. 32 bit float values require special
1637  * handling when used as locals, arguments, and in calls.
1638  * One big problem with soft-float is that there are few r4 test cases in our test suite.
1639  */
1640 void
1641 mono_decompose_soft_float (MonoCompile *cfg)
1642 {
1643         MonoBasicBlock *bb, *first_bb;
1644
1645         /*
1646          * This pass creates long opcodes, so it should be run before decompose_long_opts ().
1647          */
1648
1649         /**
1650          * Create a dummy bblock and emit code into it so we can use the normal 
1651          * code generation macros.
1652          */
1653         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1654         first_bb = cfg->cbb;
1655
1656         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1657                 MonoInst *ins;
1658                 MonoInst *prev = NULL;
1659                 gboolean restart;
1660
1661                 if (cfg->verbose_level > 3) mono_print_bb (bb, "BEFORE HANDLE-SOFT-FLOAT ");
1662
1663                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1664                 restart = TRUE;
1665
1666                 while (restart) {
1667                         restart = FALSE;
1668
1669                         for (ins = bb->code; ins; ins = ins->next) {
1670                                 const char *spec = INS_INFO (ins->opcode);
1671
1672                                 /* Most fp operations are handled automatically by opcode emulation */
1673
1674                                 switch (ins->opcode) {
1675                                 case OP_R8CONST: {
1676                                         DVal d;
1677                                         d.vald = *(double*)ins->inst_p0;
1678                                         MONO_EMIT_NEW_I8CONST (cfg, ins->dreg, d.vall);
1679                                         break;
1680                                 }
1681                                 case OP_R4CONST: {
1682                                         DVal d;
1683                                         /* We load the r8 value */
1684                                         d.vald = *(float*)ins->inst_p0;
1685                                         MONO_EMIT_NEW_I8CONST (cfg, ins->dreg, d.vall);
1686                                         break;
1687                                 }
1688                                 case OP_FMOVE:
1689                                         ins->opcode = OP_LMOVE;
1690                                         break;
1691                                 case OP_FGETLOW32:
1692                                         ins->opcode = OP_MOVE;
1693                                         ins->sreg1 = ins->sreg1 + 1;
1694                                         break;
1695                                 case OP_FGETHIGH32:
1696                                         ins->opcode = OP_MOVE;
1697                                         ins->sreg1 = ins->sreg1 + 2;
1698                                         break;
1699                                 case OP_SETFRET: {
1700                                         int reg = ins->sreg1;
1701
1702                                         ins->opcode = OP_SETLRET;
1703                                         ins->dreg = -1;
1704                                         ins->sreg1 = reg + 1;
1705                                         ins->sreg2 = reg + 2;
1706                                         break;
1707                                 }
1708                                 case OP_LOADR8_MEMBASE:
1709                                         ins->opcode = OP_LOADI8_MEMBASE;
1710                                         break;
1711                                 case OP_STORER8_MEMBASE_REG:
1712                                         ins->opcode = OP_STOREI8_MEMBASE_REG;
1713                                         break;
1714                                 case OP_STORER4_MEMBASE_REG: {
1715                                         MonoInst *iargs [2];
1716                                         int addr_reg;
1717
1718                                         /* Arg 1 is the double value */
1719                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1720                                         iargs [0]->dreg = ins->sreg1;
1721
1722                                         /* Arg 2 is the address to store to */
1723                                         addr_reg = mono_alloc_preg (cfg);
1724                                         EMIT_NEW_BIALU_IMM (cfg, iargs [1], OP_PADD_IMM, addr_reg, ins->inst_destbasereg, ins->inst_offset);
1725                                         mono_emit_jit_icall (cfg, mono_fstore_r4, iargs);
1726                                         restart = TRUE;
1727                                         break;
1728                                 }
1729                                 case OP_LOADR4_MEMBASE: {
1730                                         MonoInst *iargs [1];
1731                                         MonoInst *conv;
1732                                         int addr_reg;
1733
1734                                         addr_reg = mono_alloc_preg (cfg);
1735                                         EMIT_NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, addr_reg, ins->inst_basereg, ins->inst_offset);
1736                                         conv = mono_emit_jit_icall (cfg, mono_fload_r4, iargs);
1737                                         conv->dreg = ins->dreg;
1738                                         break;
1739                                 }                                       
1740                                 case OP_FCALL:
1741                                 case OP_FCALL_REG:
1742                                 case OP_FCALL_MEMBASE: {
1743                                         MonoCallInst *call = (MonoCallInst*)ins;
1744                                         if (call->signature->ret->type == MONO_TYPE_R4) {
1745                                                 MonoCallInst *call2;
1746                                                 MonoInst *iargs [1];
1747                                                 MonoInst *conv;
1748                                                 GSList *l;
1749
1750                                                 /* Convert the call into a call returning an int */
1751                                                 MONO_INST_NEW_CALL (cfg, call2, OP_CALL);
1752                                                 memcpy (call2, call, sizeof (MonoCallInst));
1753                                                 switch (ins->opcode) {
1754                                                 case OP_FCALL:
1755                                                         call2->inst.opcode = OP_CALL;
1756                                                         break;
1757                                                 case OP_FCALL_REG:
1758                                                         call2->inst.opcode = OP_CALL_REG;
1759                                                         break;
1760                                                 case OP_FCALL_MEMBASE:
1761                                                         call2->inst.opcode = OP_CALL_MEMBASE;
1762                                                         break;
1763                                                 default:
1764                                                         g_assert_not_reached ();
1765                                                 }
1766                                                 call2->inst.dreg = mono_alloc_ireg (cfg);
1767                                                 MONO_ADD_INS (cfg->cbb, (MonoInst*)call2);
1768
1769                                                 /* Remap OUTARG_VT instructions referencing this call */
1770                                                 for (l = call->outarg_vts; l; l = l->next)
1771                                                         ((MonoInst*)(l->data))->inst_p0 = call2;
1772
1773                                                 /* FIXME: Optimize this */
1774
1775                                                 /* Emit an r4->r8 conversion */
1776                                                 EMIT_NEW_VARLOADA_VREG (cfg, iargs [0], call2->inst.dreg, &mono_defaults.int32_class->byval_arg);
1777                                                 conv = mono_emit_jit_icall (cfg, mono_fload_r4, iargs);
1778                                                 conv->dreg = ins->dreg;
1779
1780                                                 /* The call sequence might include fp ins */
1781                                                 restart = TRUE;
1782                                         } else {
1783                                                 switch (ins->opcode) {
1784                                                 case OP_FCALL:
1785                                                         ins->opcode = OP_LCALL;
1786                                                         break;
1787                                                 case OP_FCALL_REG:
1788                                                         ins->opcode = OP_LCALL_REG;
1789                                                         break;
1790                                                 case OP_FCALL_MEMBASE:
1791                                                         ins->opcode = OP_LCALL_MEMBASE;
1792                                                         break;
1793                                                 default:
1794                                                         g_assert_not_reached ();
1795                                                 }
1796                                         }
1797                                         break;
1798                                 }
1799                                 case OP_FCOMPARE: {
1800                                         MonoJitICallInfo *info;
1801                                         MonoInst *iargs [2];
1802                                         MonoInst *call, *cmp, *br;
1803
1804                                         /* Convert fcompare+fbcc to icall+icompare+beq */
1805
1806                                         if (!ins->next) {
1807                                                 /* The branch might be optimized away */
1808                                                 NULLIFY_INS (ins);
1809                                                 break;
1810                                         }
1811
1812                                         info = mono_find_jit_opcode_emulation (ins->next->opcode);
1813                                         if (!info) {
1814                                                 /* The branch might be optimized away */
1815                                                 NULLIFY_INS (ins);
1816                                                 break;
1817                                         }
1818
1819                                         /* Create dummy MonoInst's for the arguments */
1820                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1821                                         iargs [0]->dreg = ins->sreg1;
1822                                         MONO_INST_NEW (cfg, iargs [1], OP_ARG);
1823                                         iargs [1]->dreg = ins->sreg2;
1824
1825                                         call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, iargs);
1826
1827                                         MONO_INST_NEW (cfg, cmp, OP_ICOMPARE_IMM);
1828                                         cmp->sreg1 = call->dreg;
1829                                         cmp->inst_imm = 0;
1830                                         MONO_ADD_INS (cfg->cbb, cmp);
1831                                         
1832                                         MONO_INST_NEW (cfg, br, OP_IBNE_UN);
1833                                         br->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof (gpointer) * 2);
1834                                         br->inst_true_bb = ins->next->inst_true_bb;
1835                                         br->inst_false_bb = ins->next->inst_false_bb;
1836                                         MONO_ADD_INS (cfg->cbb, br);
1837
1838                                         /* The call sequence might include fp ins */
1839                                         restart = TRUE;
1840
1841                                         /* Skip fbcc or fccc */
1842                                         NULLIFY_INS (ins->next);
1843                                         break;
1844                                 }
1845                                 case OP_FCEQ:
1846                                 case OP_FCGT:
1847                                 case OP_FCGT_UN:
1848                                 case OP_FCLT:
1849                                 case OP_FCLT_UN: {
1850                                         MonoJitICallInfo *info;
1851                                         MonoInst *iargs [2];
1852                                         MonoInst *call;
1853
1854                                         /* Convert fccc to icall+icompare+iceq */
1855
1856                                         info = mono_find_jit_opcode_emulation (ins->opcode);
1857                                         g_assert (info);
1858
1859                                         /* Create dummy MonoInst's for the arguments */
1860                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1861                                         iargs [0]->dreg = ins->sreg1;
1862                                         MONO_INST_NEW (cfg, iargs [1], OP_ARG);
1863                                         iargs [1]->dreg = ins->sreg2;
1864
1865                                         call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, iargs);
1866
1867                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, call->dreg, 1);
1868                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, ins->dreg, -1);
1869
1870                                         /* The call sequence might include fp ins */
1871                                         restart = TRUE;
1872                                         break;
1873                                 }
1874                                 case OP_CKFINITE: {
1875                                         MonoInst *iargs [2];
1876                                         MonoInst *call, *cmp;
1877
1878                                         /* Convert to icall+icompare+cond_exc+move */
1879
1880                                         /* Create dummy MonoInst's for the arguments */
1881                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1882                                         iargs [0]->dreg = ins->sreg1;
1883
1884                                         call = mono_emit_jit_icall (cfg, mono_isfinite, iargs);
1885
1886                                         MONO_INST_NEW (cfg, cmp, OP_ICOMPARE_IMM);
1887                                         cmp->sreg1 = call->dreg;
1888                                         cmp->inst_imm = 1;
1889                                         MONO_ADD_INS (cfg->cbb, cmp);
1890
1891                                         MONO_EMIT_NEW_COND_EXC (cfg, INE_UN, "ArithmeticException");
1892
1893                                         /* Do the assignment if the value is finite */
1894                                         MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, ins->dreg, ins->sreg1);
1895
1896                                         restart = TRUE;
1897                                         break;
1898                                 }
1899                                 default:
1900                                         if (spec [MONO_INST_SRC1] == 'f' || spec [MONO_INST_SRC2] == 'f' || spec [MONO_INST_DEST] == 'f') {
1901                                                 mono_print_ins (ins);
1902                                                 g_assert_not_reached ();
1903                                         }
1904                                         break;
1905                                 }
1906
1907                                 g_assert (cfg->cbb == first_bb);
1908
1909                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1910                                         /* Replace the original instruction with the new code sequence */
1911
1912                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1913                                         first_bb->code = first_bb->last_ins = NULL;
1914                                         first_bb->in_count = first_bb->out_count = 0;
1915                                         cfg->cbb = first_bb;
1916                                 }
1917                                 else
1918                                         prev = ins;
1919                         }
1920                 }
1921
1922                 if (cfg->verbose_level > 3) mono_print_bb (bb, "AFTER HANDLE-SOFT-FLOAT ");
1923         }
1924
1925         mono_decompose_long_opts (cfg);
1926 }
1927
1928 #endif
1929
1930 #endif /* DISABLE_JIT */