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