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