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