2010-01-20 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / decompose.c
1 /*
2  * decompose.c: Functions to decompose complex IR instructions into simpler ones.
3  *
4  * Author:
5  *   Zoltan Varga (vargaz@gmail.com)
6  *
7  * (C) 2002 Ximian, Inc.
8  */
9
10 #include "mini.h"
11 #include "ir-emit.h"
12
13 #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 (mono_class_from_mono_type (dest_var->inst_vtype), 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 Other ABIs might return in different regs than the ones used for LCALL.
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 */