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