2008-12-08 Atsushi Enomoto <atsushi@ximian.com>
[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  */
9
10 #include "mini.h"
11 #include "ir-emit.h"
12
13 #ifndef DISABLE_JIT
14
15 /* FIXME: This conflicts with the definition in mini.c, so it cannot be moved to mini.h */
16 MonoInst* mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature *sig, MonoInst **args);
17 void mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native);
18 void mini_emit_initobj (MonoCompile *cfg, MonoInst *dest, const guchar *ip, MonoClass *klass);
19
20 /*
21  * mono_decompose_opcode:
22  *
23  *   Decompose complex opcodes into ones closer to opcodes supported by
24  * the given architecture.
25  */
26 void
27 mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
28 {
29         /* FIXME: Instead of = NOP, don't emit the original ins at all */
30
31 #ifdef MONO_ARCH_HAVE_DECOMPOSE_OPTS
32         mono_arch_decompose_opts (cfg, ins);
33 #endif
34
35         /*
36          * The code below assumes that we are called immediately after emitting 
37          * ins. This means we can emit code using the normal code generation
38          * macros.
39          */
40         switch (ins->opcode) {
41         /* this doesn't make sense on ppc and other architectures */
42 #if !defined(MONO_ARCH_NO_IOV_CHECK)
43         case OP_IADD_OVF:
44                 ins->opcode = OP_IADDCC;
45                 MONO_EMIT_NEW_COND_EXC (cfg, IOV, "OverflowException");
46                 break;
47         case OP_IADD_OVF_UN:
48                 ins->opcode = OP_IADDCC;
49                 MONO_EMIT_NEW_COND_EXC (cfg, IC, "OverflowException");
50                 break;
51         case OP_ISUB_OVF:
52                 ins->opcode = OP_ISUBCC;
53                 MONO_EMIT_NEW_COND_EXC (cfg, IOV, "OverflowException");
54                 break;
55         case OP_ISUB_OVF_UN:
56                 ins->opcode = OP_ISUBCC;
57                 MONO_EMIT_NEW_COND_EXC (cfg, IC, "OverflowException");
58                 break;
59 #endif
60         case OP_ICONV_TO_OVF_I1:
61                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 127);
62                 MONO_EMIT_NEW_COND_EXC (cfg, IGT, "OverflowException");
63                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, -128);
64                 MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException");
65                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, ins->dreg, ins->sreg1);
66                 ins->opcode = OP_NOP;
67                 break;
68         case OP_ICONV_TO_OVF_I1_UN:
69                 /* probe values between 0 to 127 */
70                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 127);
71                 MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException");
72                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, ins->dreg, ins->sreg1);
73                 ins->opcode = OP_NOP;
74                 break;
75         case OP_ICONV_TO_OVF_U1:
76         case OP_ICONV_TO_OVF_U1_UN:
77                 /* probe value to be within 0 to 255 */
78                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 255);
79                 MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException");
80                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, ins->dreg, ins->sreg1, 0xff);
81                 ins->opcode = OP_NOP;
82                 break;
83         case OP_ICONV_TO_OVF_I2:
84                 /* Probe value to be within -32768 and 32767 */
85                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 32767);
86                 MONO_EMIT_NEW_COND_EXC (cfg, IGT, "OverflowException");
87                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, -32768);
88                 MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException");
89                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, ins->dreg, ins->sreg1);
90                 ins->opcode = OP_NOP;
91                 break;
92         case OP_ICONV_TO_OVF_I2_UN:
93                 /* Convert uint value into short, value within 0 and 32767 */
94                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 32767);
95                 MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException");
96                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, ins->dreg, ins->sreg1);
97                 ins->opcode = OP_NOP;
98                 break;
99         case OP_ICONV_TO_OVF_U2:
100         case OP_ICONV_TO_OVF_U2_UN:
101                 /* Probe value to be within 0 and 65535 */
102                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0xffff);
103                 MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException");
104                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, ins->dreg, ins->sreg1, 0xffff);
105                 ins->opcode = OP_NOP;
106                 break;
107         case OP_ICONV_TO_OVF_U4:
108         case OP_ICONV_TO_OVF_I4_UN:
109 #if SIZEOF_VOID_P == 4
110         case OP_ICONV_TO_OVF_U:
111         case OP_ICONV_TO_OVF_I_UN:
112 #endif
113                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0);
114                 MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException");
115                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
116                 ins->opcode = OP_NOP;
117                 break;
118         case OP_ICONV_TO_I4:
119         case OP_ICONV_TO_U4:
120         case OP_ICONV_TO_OVF_I4:
121 #if SIZEOF_VOID_P == 4
122         case OP_ICONV_TO_OVF_I:
123         case OP_ICONV_TO_OVF_U_UN:
124 #endif
125                 ins->opcode = OP_MOVE;
126                 break;
127         case OP_ICONV_TO_I:
128 #if SIZEOF_VOID_P == 8
129                 ins->opcode = OP_SEXT_I4;
130 #else
131                 ins->opcode = OP_MOVE;
132 #endif
133                 break;
134         case OP_ICONV_TO_U:
135 #if SIZEOF_VOID_P == 8
136                 ins->opcode = OP_ZEXT_I4;
137 #else
138                 ins->opcode = OP_MOVE;
139 #endif
140                 break;
141
142         case OP_FCONV_TO_R8:
143                 ins->opcode = OP_FMOVE;
144                 break;
145
146                 /* Long opcodes on 64 bit machines */
147 #if SIZEOF_VOID_P == 8
148         case OP_LCONV_TO_I4:
149                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_LSHR_IMM, ins->dreg, ins->sreg1, 0);
150                 ins->opcode = OP_NOP;
151                 break;
152         case OP_LCONV_TO_I8:
153         case OP_LCONV_TO_I:
154         case OP_LCONV_TO_U8:
155         case OP_LCONV_TO_U:
156                 ins->opcode = OP_MOVE;
157                 break;
158         case OP_ICONV_TO_I8:
159                 ins->opcode = OP_SEXT_I4;
160                 break;
161         case OP_ICONV_TO_U8:
162                 ins->opcode = OP_ZEXT_I4;
163                 break;
164         case OP_LCONV_TO_U4:
165                 /* Clean out the upper word */
166                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, ins->dreg, ins->sreg1, 0);
167                 ins->opcode = OP_NOP;
168                 break;
169 #if defined(__mono_ppc__) && !defined(__mono_ppc64__)
170         case OP_LADD_OVF:
171                 /* ADC sets the condition code */
172                 MONO_EMIT_NEW_BIALU (cfg, OP_ADDCC, ins->dreg + 1, ins->sreg1 + 1, ins->sreg2 + 1);
173                 MONO_EMIT_NEW_BIALU (cfg, OP_ADD_OVF_CARRY, ins->dreg + 2, ins->sreg1 + 2, ins->sreg2 + 2);
174                 ins->opcode = OP_NOP;
175                 g_assert_not_reached ();
176                 break;
177         case OP_LADD_OVF_UN:
178                 /* ADC sets the condition code */
179                 MONO_EMIT_NEW_BIALU (cfg, OP_ADDCC, ins->dreg + 1, ins->sreg1 + 1, ins->sreg2 + 1);
180                 MONO_EMIT_NEW_BIALU (cfg, OP_ADD_OVF_UN_CARRY, ins->dreg + 2, ins->sreg1 + 2, ins->sreg2 + 2);
181                 ins->opcode = OP_NOP;
182                 g_assert_not_reached ();
183                 break;
184         case OP_LSUB_OVF:
185                 /* SBB sets the condition code */
186                 MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, ins->dreg + 1, ins->sreg1 + 1, ins->sreg2 + 1);
187                 MONO_EMIT_NEW_BIALU (cfg, OP_SUB_OVF_CARRY, ins->dreg + 2, ins->sreg1 + 2, ins->sreg2 + 2);
188                 ins->opcode = OP_NOP;
189                 g_assert_not_reached ();
190                 break;
191         case OP_LSUB_OVF_UN:
192                 /* SBB sets the condition code */
193                 MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, ins->dreg + 1, ins->sreg1 + 1, ins->sreg2 + 1);
194                 MONO_EMIT_NEW_BIALU (cfg, OP_SUB_OVF_UN_CARRY, ins->dreg + 2, ins->sreg1 + 2, ins->sreg2 + 2);
195                 ins->opcode = OP_NOP;
196                 g_assert_not_reached ();
197                 break;
198 #else
199         case OP_LADD_OVF:
200                 MONO_EMIT_NEW_BIALU (cfg, OP_ADDCC, ins->dreg, ins->sreg1, ins->sreg2);
201                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
202                 ins->opcode = OP_NOP;
203                 break;
204         case OP_LADD_OVF_UN:
205                 MONO_EMIT_NEW_BIALU (cfg, OP_ADDCC, ins->dreg, ins->sreg1, ins->sreg2);
206                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
207                 ins->opcode = OP_NOP;
208                 break;
209 #ifndef __mono_ppc64__
210         case OP_LSUB_OVF:
211                 MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, ins->dreg, ins->sreg1, ins->sreg2);
212                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
213                 ins->opcode = OP_NOP;
214                 break;
215         case OP_LSUB_OVF_UN:
216                 MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, ins->dreg, ins->sreg1, ins->sreg2);
217                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
218                 ins->opcode = OP_NOP;
219                 break;
220 #endif
221 #endif
222                 
223         case OP_ICONV_TO_OVF_I8:
224         case OP_ICONV_TO_OVF_I:
225                 ins->opcode = OP_SEXT_I4;
226                 break;
227         case OP_ICONV_TO_OVF_U8:
228         case OP_ICONV_TO_OVF_U:
229                 MONO_EMIT_NEW_COMPARE_IMM (cfg,ins->sreg1, 0);
230                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
231                 MONO_EMIT_NEW_UNALU (cfg, OP_ZEXT_I4, ins->dreg, ins->sreg1);
232                 ins->opcode = OP_NOP;
233                 break;
234         case OP_ICONV_TO_OVF_I8_UN:
235         case OP_ICONV_TO_OVF_U8_UN:
236         case OP_ICONV_TO_OVF_I_UN:
237         case OP_ICONV_TO_OVF_U_UN:
238                 /* an unsigned 32 bit num always fits in an (un)signed 64 bit one */
239                 /* Clean out the upper word */
240                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, ins->dreg, ins->sreg1, 0);
241                 ins->opcode = OP_NOP;
242                 break;
243         case OP_LCONV_TO_OVF_I1:
244                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 127);
245                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
246                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, -128);
247                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
248                 MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I1, ins->dreg, ins->sreg1);
249                 ins->opcode = OP_NOP;
250                 break;
251         case OP_LCONV_TO_OVF_I1_UN:
252                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 127);
253                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
254                 MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I1, ins->dreg, ins->sreg1);
255                 ins->opcode = OP_NOP;
256                 break;
257         case OP_LCONV_TO_OVF_U1:
258                 /* probe value to be within 0 to 255 */
259                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 255);
260                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
261                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xff);
262                 ins->opcode = OP_NOP;
263                 break;
264         case OP_LCONV_TO_OVF_U1_UN:
265                 /* probe value to be within 0 to 255 */
266                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 255);
267                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
268                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xff);
269                 ins->opcode = OP_NOP;
270                 break;
271         case OP_LCONV_TO_OVF_I2:
272                 /* Probe value to be within -32768 and 32767 */
273                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 32767);
274                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
275                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, -32768);
276                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
277                 MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I2, ins->dreg, ins->sreg1);
278                 ins->opcode = OP_NOP;
279                 break;
280         case OP_LCONV_TO_OVF_I2_UN:
281                 /* Probe value to be within 0 and 32767 */
282                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 32767);
283                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
284                 MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I2, ins->dreg, ins->sreg1);
285                 ins->opcode = OP_NOP;
286                 break;
287         case OP_LCONV_TO_OVF_U2:
288                 /* Probe value to be within 0 and 65535 */
289                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 0xffff);
290                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
291                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xffff);
292                 ins->opcode = OP_NOP;
293                 break;
294         case OP_LCONV_TO_OVF_U2_UN:
295                 /* Probe value to be within 0 and 65535 */
296                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 0xffff);
297                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
298                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xffff);
299                 ins->opcode = OP_NOP;
300                 break;
301         case OP_LCONV_TO_OVF_I4:
302                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 0x7fffffff);
303                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
304                 /* The int cast is needed for the VS compiler.  See Compiler Warning (level 2) C4146. */
305                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, ((int)-2147483648));
306                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
307                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
308                 ins->opcode = OP_NOP;
309                 break;
310         case OP_LCONV_TO_OVF_I4_UN:
311                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 0x7fffffff);
312                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
313                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
314                 ins->opcode = OP_NOP;
315                 break;
316         case OP_LCONV_TO_OVF_U4:
317                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 0xffffffffUL);
318                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
319                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, ins->sreg1, 0);
320                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
321                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
322                 ins->opcode = OP_NOP;
323                 break;
324         case OP_LCONV_TO_OVF_U4_UN:
325                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 0xffffffff);
326                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
327                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
328                 ins->opcode = OP_NOP;
329                 break;
330         case OP_LCONV_TO_OVF_I:
331         case OP_LCONV_TO_OVF_U_UN:
332         case OP_LCONV_TO_OVF_U8_UN:
333                 ins->opcode = OP_MOVE;
334                 break;
335         case OP_LCONV_TO_OVF_I_UN:
336         case OP_LCONV_TO_OVF_I8_UN:
337                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, ins->sreg1, 0);
338                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
339                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
340                 ins->opcode = OP_NOP;
341                 break;
342         case OP_LCONV_TO_OVF_U8:
343         case OP_LCONV_TO_OVF_U:
344                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, ins->sreg1, 0);
345                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
346                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
347                 ins->opcode = OP_NOP;
348                 break;
349 #endif
350
351         default: {
352                 MonoJitICallInfo *info;
353
354                 info = mono_find_jit_opcode_emulation (ins->opcode);
355                 if (info) {
356                         MonoInst **args;
357                         MonoInst *call;
358
359                         /* Create dummy MonoInst's for the arguments */
360                         g_assert (!info->sig->hasthis);
361                         g_assert (info->sig->param_count <= 2);
362
363                         args = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * info->sig->param_count);
364                         if (info->sig->param_count > 0) {
365                                 MONO_INST_NEW (cfg, args [0], OP_ARG);
366                                 args [0]->dreg = ins->sreg1;
367                         }
368                         if (info->sig->param_count > 1) {
369                                 MONO_INST_NEW (cfg, args [1], OP_ARG);
370                                 args [1]->dreg = ins->sreg2;
371                         }
372
373                         call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, args);
374                         call->dreg = ins->dreg;
375
376                         ins->opcode = OP_NOP;
377                 }
378                 break;
379         }
380         }
381 }
382
383 #if SIZEOF_VOID_P == 4
384 static int lbr_decomp [][2] = {
385         {0, 0}, /* BEQ */
386         {OP_IBGT, OP_IBGE_UN}, /* BGE */
387         {OP_IBGT, OP_IBGT_UN}, /* BGT */
388         {OP_IBLT, OP_IBLE_UN}, /* BLE */
389         {OP_IBLT, OP_IBLT_UN}, /* BLT */
390         {0, 0}, /* BNE_UN */
391         {OP_IBGT_UN, OP_IBGE_UN}, /* BGE_UN */
392         {OP_IBGT_UN, OP_IBGT_UN}, /* BGT_UN */
393         {OP_IBLT_UN, OP_IBLE_UN}, /* BLE_UN */
394         {OP_IBLT_UN, OP_IBLT_UN}, /* BLT_UN */
395 };
396
397 static int lcset_decomp [][2] = {
398         {0, 0}, /* CEQ */
399         {OP_IBLT, OP_IBLE_UN}, /* CGT */
400         {OP_IBLT_UN, OP_IBLE_UN}, /* CGT_UN */
401         {OP_IBGT, OP_IBGE_UN}, /* CLT */
402         {OP_IBGT_UN, OP_IBGE_UN}, /* CLT_UN */
403 };
404 #endif
405
406 /**
407  * mono_decompose_long_opts:
408  *
409  *  Decompose 64bit opcodes into 32bit opcodes on 32 bit platforms.
410  */
411 void
412 mono_decompose_long_opts (MonoCompile *cfg)
413 {
414 #if SIZEOF_VOID_P == 4
415         MonoBasicBlock *bb, *first_bb;
416
417         /*
418          * Some opcodes, like lcall can't be decomposed so the rest of the JIT
419          * needs to be able to handle long vregs.
420          */
421
422         /* reg + 1 contains the ls word, reg + 2 contains the ms word */
423
424         /**
425          * Create a dummy bblock and emit code into it so we can use the normal 
426          * code generation macros.
427          */
428         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
429         first_bb = cfg->cbb;
430
431         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
432                 MonoInst *tree = bb->code;      
433                 MonoInst *prev = NULL;
434
435                    /*
436                 mono_print_bb (bb, "BEFORE LOWER_LONG_OPTS");
437                 */
438
439                 tree = bb->code;
440                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
441
442                 while (tree) {
443
444 #ifdef MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS
445                         mono_arch_decompose_long_opts (cfg, tree);
446 #endif
447
448                         switch (tree->opcode) {
449                         case OP_I8CONST:
450                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 1, tree->inst_ls_word);
451                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, tree->inst_ms_word);
452                                 break;
453                         case OP_LMOVE:
454                         case OP_LCONV_TO_U8:
455                         case OP_LCONV_TO_I8:
456                         case OP_LCONV_TO_OVF_U8_UN:
457                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1);
458                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2);
459                                 break;
460                         case OP_STOREI8_MEMBASE_REG:
461                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_MS_WORD_OFFSET, tree->sreg1 + 2);
462                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_LS_WORD_OFFSET, tree->sreg1 + 1);
463                                 break;
464                         case OP_LOADI8_MEMBASE:
465                                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tree->dreg + 2, tree->inst_basereg, tree->inst_offset + MINI_MS_WORD_OFFSET);
466                                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tree->dreg + 1, tree->inst_basereg, tree->inst_offset + MINI_LS_WORD_OFFSET);
467                                 break;
468
469                         case OP_ICONV_TO_I8: {
470                                 guint32 tmpreg = alloc_ireg (cfg);
471
472                                 /* branchless code:
473                                  * low = reg;
474                                  * tmp = low > -1 ? 1: 0;
475                                  * high = tmp - 1; if low is zero or pos high becomes 0, else -1
476                                  */
477                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
478                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, tree->dreg + 1, -1);
479                                 MONO_EMIT_NEW_BIALU (cfg, OP_ICGT, tmpreg, -1, -1);
480                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISUB_IMM, tree->dreg + 2, tmpreg, 1);
481                                 break;
482                         }
483                         case OP_ICONV_TO_U8:
484                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
485                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
486                                 break;
487                         case OP_ICONV_TO_OVF_I8:
488                                 /* a signed 32 bit num always fits in a signed 64 bit one */
489                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, tree->dreg + 2, tree->sreg1, 31);
490                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
491                                 break;
492                         case OP_ICONV_TO_OVF_U8:
493                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1, 0);
494                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
495                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
496                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
497                                 break;
498                         case OP_ICONV_TO_OVF_I8_UN:
499                         case OP_ICONV_TO_OVF_U8_UN:
500                                 /* an unsigned 32 bit num always fits in an (un)signed 64 bit one */
501                                 MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
502                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1);
503                                 break;
504                         case OP_LCONV_TO_I1:
505                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1);
506                                 break;
507                         case OP_LCONV_TO_U1:
508                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U1, tree->dreg, tree->sreg1 + 1);
509                                 break;
510                         case OP_LCONV_TO_I2:
511                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1);
512                                 break;
513                         case OP_LCONV_TO_U2:
514                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U2, tree->dreg, tree->sreg1 + 1);
515                                 break;
516                         case OP_LCONV_TO_I4:
517                         case OP_LCONV_TO_U4:
518                         case OP_LCONV_TO_I:
519                         case OP_LCONV_TO_U:
520                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1);
521                                 break;
522                         case OP_LCONV_TO_R8:
523                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R8_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
524                                 break;
525                         case OP_LCONV_TO_R4:
526                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R4_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
527                                 break;
528                         case OP_LCONV_TO_R_UN:
529                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R_UN_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
530                                 break;
531                         case OP_LCONV_TO_OVF_I1: {
532                                 MonoBasicBlock *is_negative, *end_label;
533
534                                 NEW_BBLOCK (cfg, is_negative);
535                                 NEW_BBLOCK (cfg, end_label);
536
537                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
538                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
539                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, -1);
540                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
541
542                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
543                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative);
544
545                                 /* Positive */
546                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 127);
547                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
548                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label);
549
550                                 /* Negative */
551                                 MONO_START_BB (cfg, is_negative);
552                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -128);
553                                 MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException");
554
555                                 MONO_START_BB (cfg, end_label);
556
557                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1);
558                                 break;
559                         }
560                         case OP_LCONV_TO_OVF_I1_UN:
561                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
562                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
563
564                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 127);
565                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
566                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -128);
567                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
568                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1);
569                                 break;
570                         case OP_LCONV_TO_OVF_U1:
571                         case OP_LCONV_TO_OVF_U1_UN:
572                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
573                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
574
575                                 /* probe value to be within 0 to 255 */
576                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 255);
577                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
578                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, tree->sreg1 + 1, 0xff);
579                                 break;
580                         case OP_LCONV_TO_OVF_I2: {
581                                 MonoBasicBlock *is_negative, *end_label;
582
583                                 NEW_BBLOCK (cfg, is_negative);
584                                 NEW_BBLOCK (cfg, end_label);
585
586                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
587                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
588                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, -1);
589                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
590
591                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
592                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative);
593
594                                 /* Positive */
595                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 32767);
596                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
597                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label);
598
599                                 /* Negative */
600                                 MONO_START_BB (cfg, is_negative);
601                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -32768);
602                                 MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException");
603                                 MONO_START_BB (cfg, end_label);
604
605                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1);
606                                 break;
607                         }
608                         case OP_LCONV_TO_OVF_I2_UN:
609                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
610                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
611
612                                 /* Probe value to be within -32768 and 32767 */
613                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 32767);
614                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
615                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -32768);
616                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
617                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1);
618                                 break;
619                         case OP_LCONV_TO_OVF_U2:
620                         case OP_LCONV_TO_OVF_U2_UN:
621                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
622                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
623
624                                 /* Probe value to be within 0 and 65535 */
625                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 0xffff);
626                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
627                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, tree->sreg1 + 1, 0xffff);
628                                 break;
629                         case OP_LCONV_TO_OVF_I4:
630                         case OP_LCONV_TO_OVF_I:
631                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_OVF_I4_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2);
632                                 break;
633                         case OP_LCONV_TO_OVF_U4:
634                         case OP_LCONV_TO_OVF_U:
635                         case OP_LCONV_TO_OVF_U4_UN:
636                         case OP_LCONV_TO_OVF_U_UN:
637                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
638                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
639                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1);
640                                 break;
641                         case OP_LCONV_TO_OVF_I_UN:
642                         case OP_LCONV_TO_OVF_I4_UN:
643                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
644                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
645                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 1, 0);
646                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
647                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1);
648                                 break;
649                         case OP_LCONV_TO_OVF_U8:
650                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
651                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
652
653                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1);
654                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2);
655                                 break;
656                         case OP_LCONV_TO_OVF_I8_UN:
657                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0);
658                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
659
660                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1);
661                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2);
662                                 break;
663
664                         case OP_LADD:
665                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
666                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
667                                 break;
668                         case OP_LSUB:
669                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
670                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
671                                 break;
672
673 #if defined(__ppc__) || defined(__powerpc__)
674                         case OP_LADD_OVF:
675                                 /* ADC sets the condition code */
676                                 MONO_EMIT_NEW_BIALU (cfg, OP_ADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
677                                 MONO_EMIT_NEW_BIALU (cfg, OP_ADD_OVF_CARRY, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
678                                 break;
679                         case OP_LADD_OVF_UN:
680                                 /* ADC sets the condition code */
681                                 MONO_EMIT_NEW_BIALU (cfg, OP_ADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
682                                 MONO_EMIT_NEW_BIALU (cfg, OP_ADD_OVF_UN_CARRY, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
683                                 break;
684                         case OP_LSUB_OVF:
685                                 /* SBB sets the condition code */
686                                 MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
687                                 MONO_EMIT_NEW_BIALU (cfg, OP_SUB_OVF_CARRY, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
688                                 break;
689                         case OP_LSUB_OVF_UN:
690                                 /* SBB sets the condition code */
691                                 MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
692                                 MONO_EMIT_NEW_BIALU (cfg, OP_SUB_OVF_UN_CARRY, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
693                                 break;
694 #else
695                         case OP_LADD_OVF:
696                                 /* ADC sets the condition code */
697                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
698                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
699                                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
700                                 break;
701                         case OP_LADD_OVF_UN:
702                                 /* ADC sets the condition code */
703                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
704                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
705                                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
706                                 break;
707                         case OP_LSUB_OVF:
708                                 /* SBB sets the condition code */
709                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
710                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
711                                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
712                                 break;
713                         case OP_LSUB_OVF_UN:
714                                 /* SBB sets the condition code */
715                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
716                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
717                                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
718                                 break;
719 #endif
720                         case OP_LAND:
721                                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
722                                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
723                                 break;
724                         case OP_LOR:
725                                 MONO_EMIT_NEW_BIALU (cfg, OP_IOR, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
726                                 MONO_EMIT_NEW_BIALU (cfg, OP_IOR, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
727                                 break;
728                         case OP_LXOR:
729                                 MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
730                                 MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
731                                 break;
732                         case OP_LNOT:
733                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 1, tree->sreg1 + 1);
734                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 2, tree->sreg1 + 2);
735                                 break;
736                         case OP_LNEG:
737                                 /* 
738                                  * FIXME: The original version in inssel-long32.brg does not work
739                                  * on x86, and the x86 version might not work on other archs ?
740                                  */
741                                 /* FIXME: Move these to mono_arch_decompose_long_opts () */
742 #if defined(__i386__)
743                                 MONO_EMIT_NEW_UNALU (cfg, OP_INEG, tree->dreg + 1, tree->sreg1 + 1);
744                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, tree->dreg + 2, tree->sreg1 + 2, 0);
745                                 MONO_EMIT_NEW_UNALU (cfg, OP_INEG, tree->dreg + 2, tree->dreg + 2);
746 #elif defined(__sparc__)
747                                 MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, tree->dreg + 1, 0, tree->sreg1 + 1);
748                                 MONO_EMIT_NEW_BIALU (cfg, OP_SBB, tree->dreg + 2, 0, tree->sreg1 + 2);
749 #elif defined(__arm__)
750                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ARM_RSBS_IMM, tree->dreg + 1, tree->sreg1 + 1, 0);
751                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ARM_RSC_IMM, tree->dreg + 2, tree->sreg1 + 2, 0);
752 #elif defined(__ppc__) || defined(__powerpc__)
753                                 /* This is the old version from inssel-long32.brg */
754                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 1, tree->sreg1 + 1);
755                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 2, tree->sreg1 + 2);
756                                 /* ADC sets the condition codes */
757                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, tree->dreg + 1, tree->dreg + 1, 1);
758                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, tree->dreg + 2, tree->dreg + 2, 0);
759 #else
760                                 NOT_IMPLEMENTED;
761 #endif
762                                 break;
763                         case OP_LMUL:
764                                 /* Emulated */
765                                 /* FIXME: Add OP_BIGMUL optimization */
766                                 break;
767
768                         case OP_LADD_IMM:
769                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADDCC_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
770                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
771                                 break;
772                         case OP_LSUB_IMM:
773                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUBCC_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
774                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SBB_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
775                                 break;
776                         case OP_LAND_IMM:
777                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
778                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
779                                 break;
780                         case OP_LOR_IMM:
781                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
782                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
783                                 break;
784                         case OP_LXOR_IMM:
785                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word);
786                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word);
787                                 break;
788                         case OP_LSHR_UN_IMM:
789                                 if (tree->inst_c1 == 32) {
790
791                                         /* The original code had this comment: */
792                                         /* special case that gives a nice speedup and happens to workaorund a ppc jit but (for the release)
793                                          * later apply the speedup to the left shift as well
794                                          * See BUG# 57957.
795                                          */
796                                         /* FIXME: Move this to the strength reduction pass */
797                                         /* just move the upper half to the lower and zero the high word */
798                                         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 2);
799                                         MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0);
800                                 }
801                                 break;
802                         case OP_LSHL_IMM:
803                                 if (tree->inst_c1 == 32) {
804                                         /* just move the lower half to the upper and zero the lower word */
805                                         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 1);
806                                         MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 1, 0);
807                                 }
808                                 break;
809
810                         case OP_LCOMPARE: {
811                                 MonoInst *next = tree->next;
812
813                                 g_assert (next);
814
815                                 switch (next->opcode) {
816                                 case OP_LBEQ:
817                                 case OP_LBNE_UN: {
818                                         int d1, d2;
819
820                                         /* Branchless version based on gcc code */
821                                         d1 = alloc_ireg (cfg);
822                                         d2 = alloc_ireg (cfg);
823                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, tree->sreg1 + 1, tree->sreg2 + 1);
824                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, tree->sreg1 + 2, tree->sreg2 + 2);
825                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
826                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
827                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
828                                         next->opcode = OP_NOP;
829                                         break;
830                                 }
831                                 case OP_LBGE:
832                                 case OP_LBGT:
833                                 case OP_LBLE:
834                                 case OP_LBLT:
835                                 case OP_LBGE_UN:
836                                 case OP_LBGT_UN:
837                                 case OP_LBLE_UN:
838                                 case OP_LBLT_UN:
839                                         /* Convert into three comparisons + branches */
840                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
841                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lbr_decomp [next->opcode - OP_LBEQ][0], next->inst_true_bb);
842                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
843                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
844                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1);
845                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
846                                         next->opcode = OP_NOP;
847                                         break;
848                                 case OP_LCEQ: {
849                                         int d1, d2;
850         
851                                         /* Branchless version based on gcc code */
852                                         d1 = alloc_ireg (cfg);
853                                         d2 = alloc_ireg (cfg);
854                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, tree->sreg1 + 1, tree->sreg2 + 1);
855                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, tree->sreg1 + 2, tree->sreg2 + 2);
856                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
857
858                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
859                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
860                                         next->opcode = OP_NOP;
861                                         break;
862                                 }
863                                 case OP_LCLT:
864                                 case OP_LCLT_UN:
865                                 case OP_LCGT:
866                                 case OP_LCGT_UN: {
867                                         MonoBasicBlock *set_to_0, *set_to_1;
868         
869                                         NEW_BBLOCK (cfg, set_to_0);
870                                         NEW_BBLOCK (cfg, set_to_1);
871
872                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 0);
873                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
874                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][0], set_to_0);
875                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2);
876                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, set_to_1);
877                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1);
878                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][1], set_to_0);
879                                         MONO_START_BB (cfg, set_to_1);
880                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
881                                         MONO_START_BB (cfg, set_to_0);
882                                         next->opcode = OP_NOP;
883                                         break;  
884                                 }
885                                 default:
886                                         g_assert_not_reached ();
887                                 }
888                                 break;
889                         }
890
891                         /* Not yet used, since lcompare is decomposed before local cprop */
892                         case OP_LCOMPARE_IMM: {
893                                 MonoInst *next = tree->next;
894                                 guint32 low_imm = tree->inst_ls_word;
895                                 guint32 high_imm = tree->inst_ms_word;
896                                 int low_reg = tree->sreg1 + 1;
897                                 int high_reg = tree->sreg1 + 2;
898
899                                 g_assert (next);
900
901                                 switch (next->opcode) {
902                                 case OP_LBEQ:
903                                 case OP_LBNE_UN: {
904                                         int d1, d2;
905
906                                         /* Branchless version based on gcc code */
907                                         d1 = alloc_ireg (cfg);
908                                         d2 = alloc_ireg (cfg);
909                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d1, low_reg, low_imm);
910                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d2, high_reg, high_imm);
911                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
912                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
913                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
914                                         next->opcode = OP_NOP;
915                                         break;
916                                 }
917
918                                 case OP_LBGE:
919                                 case OP_LBGT:
920                                 case OP_LBLE:
921                                 case OP_LBLT:
922                                 case OP_LBGE_UN:
923                                 case OP_LBGT_UN:
924                                 case OP_LBLE_UN:
925                                 case OP_LBLT_UN:
926                                         /* Convert into three comparisons + branches */
927                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
928                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lbr_decomp [next->opcode - OP_LBEQ][0], next->inst_true_bb);
929                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
930                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
931                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
932                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
933                                         next->opcode = OP_NOP;
934                                         break;
935                                 case OP_LCEQ: {
936                                         int d1, d2;
937         
938                                         /* Branchless version based on gcc code */
939                                         d1 = alloc_ireg (cfg);
940                                         d2 = alloc_ireg (cfg);
941                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d1, low_reg, low_imm);
942                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d2, high_reg, high_imm);
943                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
944
945                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
946                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
947                                         next->opcode = OP_NOP;
948                                         break;
949                                 }
950                                 case OP_LCLT:
951                                 case OP_LCLT_UN:
952                                 case OP_LCGT:
953                                 case OP_LCGT_UN: {
954                                         MonoBasicBlock *set_to_0, *set_to_1;
955         
956                                         NEW_BBLOCK (cfg, set_to_0);
957                                         NEW_BBLOCK (cfg, set_to_1);
958
959                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 0);
960                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
961                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][0], set_to_0);
962                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
963                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, set_to_1);
964                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
965                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][1], set_to_0);
966                                         MONO_START_BB (cfg, set_to_1);
967                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
968                                         MONO_START_BB (cfg, set_to_0);
969                                         next->opcode = OP_NOP;
970                                         break;  
971                                 }
972                                 default:
973                                         g_assert_not_reached ();
974                                 }
975                                 break;
976                         }
977
978                         default:
979                                 break;
980                         }
981
982                         if (cfg->cbb->code || (cfg->cbb != first_bb)) {
983                                 MonoInst *new_prev;
984
985                                 /* Replace the original instruction with the new code sequence */
986
987                                 /* Ignore the new value of prev */
988                                 new_prev = prev;
989                                 mono_replace_ins (cfg, bb, tree, &new_prev, first_bb, cfg->cbb);
990
991                                 /* Process the newly added ops again since they can be long ops too */
992                                 if (prev)
993                                         tree = prev->next;
994                                 else
995                                         tree = bb->code;
996
997                                 first_bb->code = first_bb->last_ins = NULL;
998                                 first_bb->in_count = first_bb->out_count = 0;
999                                 cfg->cbb = first_bb;
1000                         }
1001                         else {
1002                                 prev = tree;
1003                                 tree = tree->next;
1004                         }
1005                 }
1006         }
1007 #endif
1008
1009         /*
1010         for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
1011                 mono_print_bb (bb, "AFTER LOWER-LONG-OPTS");
1012         */
1013 }
1014
1015 /**
1016  * mono_decompose_vtype_opts:
1017  *
1018  *  Decompose valuetype opcodes.
1019  */
1020 void
1021 mono_decompose_vtype_opts (MonoCompile *cfg)
1022 {
1023         MonoBasicBlock *bb, *first_bb;
1024
1025         /**
1026          * Using OP_V opcodes and decomposing them later have two main benefits:
1027          * - it simplifies method_to_ir () since there is no need to special-case vtypes
1028          *   everywhere.
1029          * - it gets rid of the LDADDR opcodes generated when vtype operations are decomposed,
1030          *   enabling optimizations to work on vtypes too.
1031          * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it 
1032          * can be executed anytime. It should be executed as late as possible so vtype
1033          * opcodes can be optimized by the other passes.
1034          * The pinvoke wrappers need to manipulate vtypes in their unmanaged representation.
1035          * This is indicated by setting the 'backend.is_pinvoke' field of the MonoInst for the 
1036          * var to 1.
1037          * This is done on demand, ie. by the LDNATIVEOBJ opcode, and propagated by this pass 
1038          * when OP_VMOVE opcodes are decomposed.
1039          */
1040
1041         /* 
1042          * Vregs have no associated type information, so we store the type of the vregs
1043          * in ins->klass.
1044          */
1045
1046         /**
1047          * Create a dummy bblock and emit code into it so we can use the normal 
1048          * code generation macros.
1049          */
1050         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1051         first_bb = cfg->cbb;
1052
1053         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1054                 MonoInst *ins;
1055                 MonoInst *prev = NULL;
1056                 MonoInst *src_var, *dest_var, *src, *dest;
1057                 gboolean restart;
1058                 int dreg;
1059
1060                 if (cfg->verbose_level > 2) mono_print_bb (bb, "BEFORE LOWER-VTYPE-OPTS ");
1061
1062                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1063                 restart = TRUE;
1064
1065                 while (restart) {
1066                         restart = FALSE;
1067
1068                         for (ins = bb->code; ins; ins = ins->next) {
1069                                 switch (ins->opcode) {
1070                                 case OP_VMOVE: {
1071                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1072                                         dest_var = get_vreg_to_inst (cfg, ins->dreg);
1073
1074                                         g_assert (ins->klass);
1075
1076                                         if (!src_var)
1077                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1078
1079                                         if (!dest_var)
1080                                                 dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1081
1082                                         // FIXME:
1083                                         if (src_var->backend.is_pinvoke)
1084                                                 dest_var->backend.is_pinvoke = 1;
1085
1086                                         EMIT_NEW_VARLOADA ((cfg), (src), src_var, src_var->inst_vtype);
1087                                         EMIT_NEW_VARLOADA ((cfg), (dest), dest_var, dest_var->inst_vtype);
1088
1089                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1090                                         break;
1091                                 }
1092                                 case OP_VZERO:
1093                                         g_assert (ins->klass);
1094
1095                                         EMIT_NEW_VARLOADA_VREG (cfg, dest, ins->dreg, &ins->klass->byval_arg);
1096                                         mini_emit_initobj (cfg, dest, NULL, ins->klass);
1097                                         break;
1098                                 case OP_STOREV_MEMBASE: {
1099                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1100
1101                                         if (!src_var) {
1102                                                 g_assert (ins->klass);
1103                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1104                                         }
1105
1106                                         EMIT_NEW_VARLOADA_VREG ((cfg), (src), ins->sreg1, &ins->klass->byval_arg);
1107
1108                                         dreg = alloc_preg (cfg);
1109                                         EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
1110                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1111                                         break;
1112                                 }
1113                                 case OP_LOADV_MEMBASE: {
1114                                         g_assert (ins->klass);
1115
1116                                         dest_var = get_vreg_to_inst (cfg, ins->dreg);
1117                                         // FIXME:
1118                                         if (!dest_var)
1119                                                 dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1120
1121                                         dreg = alloc_preg (cfg);
1122                                         EMIT_NEW_BIALU_IMM (cfg, src, OP_ADD_IMM, dreg, ins->inst_basereg, ins->inst_offset);
1123                                         EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
1124                                         mini_emit_stobj (cfg, dest, src, dest_var->klass, dest_var->backend.is_pinvoke);
1125                                         break;
1126                                 }
1127                                 case OP_OUTARG_VT: {
1128                                         g_assert (ins->klass);
1129
1130                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1131                                         if (!src_var)
1132                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1133                                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
1134
1135                                         mono_arch_emit_outarg_vt (cfg, ins, src);
1136
1137                                         /* This might be decomposed into other vtype opcodes */
1138                                         restart = TRUE;
1139                                         break;
1140                                 }
1141                                 case OP_OUTARG_VTRETADDR: {
1142                                         MonoCallInst *call = (MonoCallInst*)ins->inst_p1;
1143
1144                                         src_var = get_vreg_to_inst (cfg, call->inst.dreg);
1145                                         if (!src_var)
1146                                                 src_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
1147                                         // FIXME: src_var->backend.is_pinvoke ?
1148
1149                                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
1150                                         src->dreg = ins->dreg;
1151                                         break;
1152                                 }
1153                                 case OP_VCALL:
1154                                 case OP_VCALL_REG:
1155                                 case OP_VCALL_MEMBASE: {
1156                                         MonoCallInst *call = (MonoCallInst*)ins;
1157                                         int size;
1158
1159                                         if (call->vret_in_reg) {
1160                                                 MonoCallInst *call2;
1161
1162                                                 /* Replace the vcall with an integer call */
1163                                                 MONO_INST_NEW_CALL (cfg, call2, OP_NOP);
1164                                                 memcpy (call2, call, sizeof (MonoCallInst));
1165                                                 switch (ins->opcode) {
1166                                                 case OP_VCALL:
1167                                                         call2->inst.opcode = OP_CALL;
1168                                                         break;
1169                                                 case OP_VCALL_REG:
1170                                                         call2->inst.opcode = OP_CALL_REG;
1171                                                         break;
1172                                                 case OP_VCALL_MEMBASE:
1173                                                         call2->inst.opcode = OP_CALL_MEMBASE;
1174                                                         break;
1175                                                 }
1176                                                 call2->inst.dreg = alloc_preg (cfg);
1177                                                 MONO_ADD_INS (cfg->cbb, ((MonoInst*)call2));
1178
1179                                                 /* Compute the vtype location */
1180                                                 dest_var = get_vreg_to_inst (cfg, call->inst.dreg);
1181                                                 if (!dest_var)
1182                                                         dest_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
1183                                                 EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
1184
1185                                                 /* Save the result */
1186                                                 if (dest_var->backend.is_pinvoke)
1187                                                         size = mono_class_native_size (dest->inst_vtype->data.klass, NULL);
1188                                                 else
1189                                                         size = mono_type_size (dest_var->inst_vtype, NULL);
1190                                                 switch (size) {
1191                                                 case 1:
1192                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1193                                                         break;
1194                                                 case 2:
1195                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1196                                                         break;
1197                                                 case 4:
1198                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1199                                                         break;
1200                                                 case 8:
1201                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1202                                                         break;
1203                                                 default:
1204                                                         /* This assumes the vtype is sizeof (gpointer) long */
1205                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1206                                                         break;
1207                                                 }
1208                                         } else {
1209                                                 switch (ins->opcode) {
1210                                                 case OP_VCALL:
1211                                                         ins->opcode = OP_VCALL2;
1212                                                         break;
1213                                                 case OP_VCALL_REG:
1214                                                         ins->opcode = OP_VCALL2_REG;
1215                                                         break;
1216                                                 case OP_VCALL_MEMBASE:
1217                                                         ins->opcode = OP_VCALL2_MEMBASE;
1218                                                         break;
1219                                                 }
1220                                                 ins->dreg = -1;
1221                                         }
1222                                         break;
1223                                 }
1224                                 default:
1225                                         break;
1226                                 }
1227
1228                                 g_assert (cfg->cbb == first_bb);
1229
1230                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1231                                         /* Replace the original instruction with the new code sequence */
1232
1233                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1234                                         first_bb->code = first_bb->last_ins = NULL;
1235                                         first_bb->in_count = first_bb->out_count = 0;
1236                                         cfg->cbb = first_bb;
1237                                 }
1238                                 else
1239                                         prev = ins;
1240                         }
1241                 }
1242
1243                 if (cfg->verbose_level > 2) mono_print_bb (bb, "AFTER LOWER-VTYPE-OPTS ");
1244         }
1245 }
1246
1247 #endif /* DISABLE_JIT */