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