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