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