d8c46e88c0d87377365817747d1f59495e8790cf
[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  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
9  */
10
11 #include "mini.h"
12 #include "ir-emit.h"
13 #include "jit-icalls.h"
14
15 #include <mono/metadata/gc-internals.h>
16 #include <mono/metadata/abi-details.h>
17
18 #ifndef DISABLE_JIT
19
20 /* FIXME: This conflicts with the definition in mini.c, so it cannot be moved to mini.h */
21 MONO_API MonoInst* mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature *sig, MonoInst **args);
22 void mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native);
23 void mini_emit_initobj (MonoCompile *cfg, MonoInst *dest, const guchar *ip, MonoClass *klass);
24
25 /*
26  * Decompose complex long opcodes on 64 bit machines.
27  * This is also used on 32 bit machines when using LLVM, so it needs to handle I/U correctly.
28  */
29 static gboolean
30 decompose_long_opcode (MonoCompile *cfg, MonoInst *ins, MonoInst **repl_ins)
31 {
32         MonoInst *repl = NULL;
33
34         *repl_ins = NULL;
35
36         switch (ins->opcode) {
37         case OP_LCONV_TO_I4:
38                 ins->opcode = OP_SEXT_I4;
39                 break;
40         case OP_LCONV_TO_I8:
41         case OP_LCONV_TO_U8:
42                 if (SIZEOF_VOID_P == 4)
43                         ins->opcode = OP_LMOVE;
44                 else
45                         ins->opcode = OP_MOVE;
46                 break;
47         case OP_LCONV_TO_I:
48                 if (SIZEOF_VOID_P == 4)
49                         /* OP_LCONV_TO_I4 */
50                         ins->opcode = OP_SEXT_I4;
51                 else
52                         ins->opcode = OP_MOVE;
53                 break;
54         case OP_LCONV_TO_U:
55                 if (SIZEOF_VOID_P == 4) {
56                         /* OP_LCONV_TO_U4 */
57                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, ins->dreg, ins->sreg1, 0);
58                         NULLIFY_INS (ins);
59                 } else {
60                         ins->opcode = OP_MOVE;
61                 }
62                 break;
63         case OP_ICONV_TO_I8:
64                 ins->opcode = OP_SEXT_I4;
65                 break;
66         case OP_ICONV_TO_U8:
67                 ins->opcode = OP_ZEXT_I4;
68                 break;
69         case OP_LCONV_TO_U4:
70                 /* Clean out the upper word */
71                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, ins->dreg, ins->sreg1, 0);
72                 NULLIFY_INS (ins);
73                 break;
74         case OP_LADD_OVF: {
75                 int opcode;
76
77                 if (COMPILE_LLVM (cfg))
78                         break;
79                 if (cfg->backend->ilp32 && SIZEOF_REGISTER == 8)
80                         opcode = OP_LADDCC;
81                 else
82                         opcode = OP_ADDCC;
83                 EMIT_NEW_BIALU (cfg, repl, opcode, ins->dreg, ins->sreg1, ins->sreg2);
84                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
85                 NULLIFY_INS (ins);
86                 break;
87         }
88         case OP_LADD_OVF_UN: {
89                 int opcode;
90
91                 if (COMPILE_LLVM (cfg))
92                         break;
93                 if (cfg->backend->ilp32 && SIZEOF_REGISTER == 8)
94                         opcode = OP_LADDCC;
95                 else
96                         opcode = OP_ADDCC;
97                 EMIT_NEW_BIALU (cfg, repl, opcode, ins->dreg, ins->sreg1, ins->sreg2);
98                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
99                 NULLIFY_INS (ins);
100                 break;
101         }
102 #ifndef __mono_ppc64__
103         case OP_LSUB_OVF: {
104                 int opcode;
105
106                 if (COMPILE_LLVM (cfg))
107                         break;
108                 if (cfg->backend->ilp32 && SIZEOF_REGISTER == 8)
109                         opcode = OP_LSUBCC;
110                 else
111                         opcode = OP_SUBCC;
112                 EMIT_NEW_BIALU (cfg, repl, opcode, ins->dreg, ins->sreg1, ins->sreg2);
113                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
114                 NULLIFY_INS (ins);
115                 break;
116         }
117         case OP_LSUB_OVF_UN: {
118                 int opcode;
119
120                 if (COMPILE_LLVM (cfg))
121                         break;
122                 if (cfg->backend->ilp32 && SIZEOF_REGISTER == 8)
123                         opcode = OP_LSUBCC;
124                 else
125                         opcode = OP_SUBCC;
126                 EMIT_NEW_BIALU (cfg, repl, opcode, ins->dreg, ins->sreg1, ins->sreg2);
127                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
128                 NULLIFY_INS (ins);
129                 break;
130         }
131 #endif
132                 
133         case OP_ICONV_TO_OVF_I8:
134         case OP_ICONV_TO_OVF_I:
135                 ins->opcode = OP_SEXT_I4;
136                 break;
137         case OP_ICONV_TO_OVF_U8:
138         case OP_ICONV_TO_OVF_U:
139                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg,ins->sreg1, 0);
140                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
141                 MONO_EMIT_NEW_UNALU (cfg, OP_ZEXT_I4, ins->dreg, ins->sreg1);
142                 NULLIFY_INS (ins);
143                 break;
144         case OP_ICONV_TO_OVF_I8_UN:
145         case OP_ICONV_TO_OVF_U8_UN:
146         case OP_ICONV_TO_OVF_I_UN:
147         case OP_ICONV_TO_OVF_U_UN:
148                 /* an unsigned 32 bit num always fits in an (un)signed 64 bit one */
149                 /* Clean out the upper word */
150                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, ins->dreg, ins->sreg1, 0);
151                 NULLIFY_INS (ins);
152                 break;
153         case OP_LCONV_TO_OVF_I1:
154                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 127);
155                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
156                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, -128);
157                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
158                 MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I1, ins->dreg, ins->sreg1);
159                 NULLIFY_INS (ins);
160                 break;
161         case OP_LCONV_TO_OVF_I1_UN:
162                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 127);
163                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
164                 MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I1, ins->dreg, ins->sreg1);
165                 NULLIFY_INS (ins);
166                 break;
167         case OP_LCONV_TO_OVF_U1:
168                 /* probe value to be within 0 to 255 */
169                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 255);
170                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
171                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xff);
172                 NULLIFY_INS (ins);
173                 break;
174         case OP_LCONV_TO_OVF_U1_UN:
175                 /* probe value to be within 0 to 255 */
176                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 255);
177                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
178                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xff);
179                 NULLIFY_INS (ins);
180                 break;
181         case OP_LCONV_TO_OVF_I2:
182                 /* Probe value to be within -32768 and 32767 */
183                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 32767);
184                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
185                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, -32768);
186                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
187                 MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I2, ins->dreg, ins->sreg1);
188                 NULLIFY_INS (ins);
189                 break;
190         case OP_LCONV_TO_OVF_I2_UN:
191                 /* Probe value to be within 0 and 32767 */
192                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 32767);
193                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
194                 MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I2, ins->dreg, ins->sreg1);
195                 NULLIFY_INS (ins);
196                 break;
197         case OP_LCONV_TO_OVF_U2:
198                 /* Probe value to be within 0 and 65535 */
199                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0xffff);
200                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
201                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xffff);
202                 NULLIFY_INS (ins);
203                 break;
204         case OP_LCONV_TO_OVF_U2_UN:
205                 /* Probe value to be within 0 and 65535 */
206                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0xffff);
207                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
208                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, ins->dreg, ins->sreg1, 0xffff);
209                 NULLIFY_INS (ins);
210                 break;
211         case OP_LCONV_TO_OVF_I4:
212 #if SIZEOF_VOID_P == 4
213         case OP_LCONV_TO_OVF_I:
214 #endif
215                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0x7fffffff);
216                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
217                 /* The int cast is needed for the VS compiler.  See Compiler Warning (level 2) C4146. */
218 #if SIZEOF_REGISTER == 8
219                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, ((int)-2147483648));
220 #else
221                 g_assert (COMPILE_LLVM (cfg));
222                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, -2147483648LL);
223 #endif
224                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
225                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
226                 NULLIFY_INS (ins);
227                 break;
228         case OP_LCONV_TO_OVF_I4_UN:
229 #if SIZEOF_VOID_P == 4
230         case OP_LCONV_TO_OVF_I_UN:
231 #endif
232                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0x7fffffff);
233                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
234                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
235                 NULLIFY_INS (ins);
236                 break;
237         case OP_LCONV_TO_OVF_U4:
238 #if SIZEOF_VOID_P == 4
239         case OP_LCONV_TO_OVF_U:
240 #endif
241                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0xffffffffUL);
242                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
243                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0);
244                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
245                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
246                 NULLIFY_INS (ins);
247                 break;
248         case OP_LCONV_TO_OVF_U4_UN:
249 #if SIZEOF_VOID_P == 4
250         case OP_LCONV_TO_OVF_U_UN:
251 #endif
252                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0xffffffff);
253                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
254                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
255                 NULLIFY_INS (ins);
256                 break;
257 #if SIZEOF_VOID_P == 8
258         case OP_LCONV_TO_OVF_I:
259         case OP_LCONV_TO_OVF_U_UN:
260 #endif
261         case OP_LCONV_TO_OVF_U8_UN:
262         case OP_LCONV_TO_OVF_I8:
263                 ins->opcode = OP_MOVE;
264                 break;
265 #if SIZEOF_VOID_P == 8
266         case OP_LCONV_TO_OVF_I_UN:
267 #endif
268         case OP_LCONV_TO_OVF_I8_UN:
269                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0);
270                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
271                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
272                 NULLIFY_INS (ins);
273                 break;
274         case OP_LCONV_TO_OVF_U8:
275 #if SIZEOF_VOID_P == 8
276         case OP_LCONV_TO_OVF_U:
277 #endif
278                 MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg1, 0);
279                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
280                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
281                 NULLIFY_INS (ins);
282                 break;
283         default:
284                 return FALSE;
285         }
286
287         *repl_ins = repl;
288         return TRUE;
289 }
290
291 /*
292  * mono_decompose_opcode:
293  *
294  *   Decompose complex opcodes into ones closer to opcodes supported by
295  * the given architecture.
296  * Returns a MonoInst which represents the result of the decomposition, and can
297  * be pushed on the IL stack. This is needed because the original instruction is
298  * nullified.
299  * Sets the cfg exception if an opcode is not supported.
300  */
301 MonoInst*
302 mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
303 {
304         MonoInst *repl = NULL;
305         int type = ins->type;
306         int dreg = ins->dreg;
307         gboolean emulate = FALSE;
308
309         /* FIXME: Instead of = NOP, don't emit the original ins at all */
310         mono_arch_decompose_opts (cfg, ins);
311
312         /*
313          * The code below assumes that we are called immediately after emitting 
314          * ins. This means we can emit code using the normal code generation
315          * macros.
316          */
317         switch (ins->opcode) {
318         /* this doesn't make sense on ppc and other architectures */
319 #if !defined(MONO_ARCH_NO_IOV_CHECK)
320         case OP_IADD_OVF:
321                 if (COMPILE_LLVM (cfg))
322                         break;
323                 ins->opcode = OP_IADDCC;
324                 MONO_EMIT_NEW_COND_EXC (cfg, IOV, "OverflowException");
325                 break;
326         case OP_IADD_OVF_UN:
327                 if (COMPILE_LLVM (cfg))
328                         break;
329                 ins->opcode = OP_IADDCC;
330                 MONO_EMIT_NEW_COND_EXC (cfg, IC, "OverflowException");
331                 break;
332         case OP_ISUB_OVF:
333                 if (COMPILE_LLVM (cfg))
334                         break;
335                 ins->opcode = OP_ISUBCC;
336                 MONO_EMIT_NEW_COND_EXC (cfg, IOV, "OverflowException");
337                 break;
338         case OP_ISUB_OVF_UN:
339                 if (COMPILE_LLVM (cfg))
340                         break;
341                 ins->opcode = OP_ISUBCC;
342                 MONO_EMIT_NEW_COND_EXC (cfg, IC, "OverflowException");
343                 break;
344 #endif
345         case OP_ICONV_TO_OVF_I1:
346                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 127);
347                 MONO_EMIT_NEW_COND_EXC (cfg, IGT, "OverflowException");
348                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, -128);
349                 MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException");
350                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, ins->dreg, ins->sreg1);
351                 NULLIFY_INS (ins);
352                 break;
353         case OP_ICONV_TO_OVF_I1_UN:
354                 /* probe values between 0 to 127 */
355                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 127);
356                 MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException");
357                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, ins->dreg, ins->sreg1);
358                 NULLIFY_INS (ins);
359                 break;
360         case OP_ICONV_TO_OVF_U1:
361         case OP_ICONV_TO_OVF_U1_UN:
362                 /* probe value to be within 0 to 255 */
363                 MONO_EMIT_NEW_COMPARE_IMM (cfg, ins->sreg1, 255);
364                 MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException");
365                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, ins->dreg, ins->sreg1, 0xff);
366                 NULLIFY_INS (ins);
367                 break;
368         case OP_ICONV_TO_OVF_I2:
369                 /* Probe value to be within -32768 and 32767 */
370                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 32767);
371                 MONO_EMIT_NEW_COND_EXC (cfg, IGT, "OverflowException");
372                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, -32768);
373                 MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException");
374                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, ins->dreg, ins->sreg1);
375                 NULLIFY_INS (ins);
376                 break;
377         case OP_ICONV_TO_OVF_I2_UN:
378                 /* Convert uint value into short, value within 0 and 32767 */
379                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 32767);
380                 MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException");
381                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, ins->dreg, ins->sreg1);
382                 NULLIFY_INS (ins);
383                 break;
384         case OP_ICONV_TO_OVF_U2:
385         case OP_ICONV_TO_OVF_U2_UN:
386                 /* Probe value to be within 0 and 65535 */
387                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0xffff);
388                 MONO_EMIT_NEW_COND_EXC (cfg, IGT_UN, "OverflowException");
389                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, ins->dreg, ins->sreg1, 0xffff);
390                 NULLIFY_INS (ins);
391                 break;
392         case OP_ICONV_TO_OVF_U4:
393         case OP_ICONV_TO_OVF_I4_UN:
394 #if SIZEOF_VOID_P == 4
395         case OP_ICONV_TO_OVF_U:
396         case OP_ICONV_TO_OVF_I_UN:
397 #endif
398                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0);
399                 MONO_EMIT_NEW_COND_EXC (cfg, ILT, "OverflowException");
400                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, ins->sreg1);
401                 NULLIFY_INS (ins);
402                 break;
403         case OP_ICONV_TO_I4:
404         case OP_ICONV_TO_U4:
405         case OP_ICONV_TO_OVF_I4:
406         case OP_ICONV_TO_OVF_U4_UN:
407 #if SIZEOF_VOID_P == 4
408         case OP_ICONV_TO_OVF_I:
409         case OP_ICONV_TO_OVF_U_UN:
410 #endif
411                 ins->opcode = OP_MOVE;
412                 break;
413         case OP_ICONV_TO_I:
414 #if SIZEOF_VOID_P == 8
415                 ins->opcode = OP_SEXT_I4;
416 #else
417                 ins->opcode = OP_MOVE;
418 #endif
419                 break;
420         case OP_ICONV_TO_U:
421 #if SIZEOF_VOID_P == 8
422                 ins->opcode = OP_ZEXT_I4;
423 #else
424                 ins->opcode = OP_MOVE;
425 #endif
426                 break;
427
428         case OP_FCONV_TO_R8:
429                 ins->opcode = OP_FMOVE;
430                 break;
431
432         case OP_FCONV_TO_OVF_I1_UN:
433         case OP_FCONV_TO_OVF_I2_UN:
434         case OP_FCONV_TO_OVF_I4_UN:
435         case OP_FCONV_TO_OVF_I8_UN:
436         case OP_FCONV_TO_OVF_U1_UN:
437         case OP_FCONV_TO_OVF_U2_UN:
438         case OP_FCONV_TO_OVF_U4_UN:
439         case OP_FCONV_TO_OVF_U8_UN:
440         case OP_FCONV_TO_OVF_I_UN:
441         case OP_FCONV_TO_OVF_U_UN:
442                 mono_cfg_set_exception_invalid_program (cfg, g_strdup_printf ("float conv.ovf.un opcodes not supported."));
443                 break;
444
445         case OP_IDIV:
446         case OP_IREM:
447         case OP_IDIV_UN:
448         case OP_IREM_UN:
449                 if (cfg->backend->emulate_div && mono_arch_opcode_needs_emulation (cfg, ins->opcode))
450                         emulate = TRUE;
451                 if (!emulate) {
452                         if (cfg->backend->need_div_check) {
453                                 int reg1 = alloc_ireg (cfg);
454                                 int reg2 = alloc_ireg (cfg);
455                                 /* b == 0 */
456                                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg2, 0);
457                                 MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "DivideByZeroException");
458                                 if (ins->opcode == OP_IDIV || ins->opcode == OP_IREM) {
459                                         /* b == -1 && a == 0x80000000 */
460                                         MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg2, -1);
461                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, reg1, -1);
462                                         MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0x80000000);
463                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, reg2, -1);
464                                         MONO_EMIT_NEW_BIALU (cfg, OP_IAND, reg1, reg1, reg2);
465                                         MONO_EMIT_NEW_ICOMPARE_IMM (cfg, reg1, 1);
466                                         MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "OverflowException");
467                                 }
468                         }
469                         MONO_EMIT_NEW_BIALU (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->sreg2);
470                         NULLIFY_INS (ins);
471                 }
472                 break;
473
474 #if SIZEOF_REGISTER == 8
475         case OP_LREM_IMM:
476 #endif
477         case OP_IREM_IMM: {
478                 int power = mono_is_power_of_two (ins->inst_imm);
479                 if (ins->inst_imm == 1) {
480                         ins->opcode = OP_ICONST;
481                         MONO_INST_NULLIFY_SREGS (ins);
482                         ins->inst_c0 = 0;
483 #if __s390__
484                 }
485 #else
486                 } else if ((ins->inst_imm > 0) && (ins->inst_imm < (1LL << 32)) && (power != -1)) {
487                         gboolean is_long = ins->opcode == OP_LREM_IMM;
488                         int compensator_reg = alloc_ireg (cfg);
489                         int intermediate_reg;
490
491                         /* Based on gcc code */
492
493                         /* Add compensation for negative numerators */
494
495                         if (power > 1) {
496                                 intermediate_reg = compensator_reg;
497                                 MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_ISHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31);
498                         } else {
499                                 intermediate_reg = ins->sreg1;
500                         }
501
502                         MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_ISHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power);
503                         MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LADD : OP_IADD, ins->dreg, ins->sreg1, compensator_reg);
504                         /* Compute remainder */
505                         MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LAND_IMM : OP_AND_IMM, ins->dreg, ins->dreg, (1 << power) - 1);
506                         /* Remove compensation */
507                         MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LSUB : OP_ISUB, ins->dreg, ins->dreg, compensator_reg);
508
509                         NULLIFY_INS (ins);
510                 }
511 #endif
512                 break;
513         }
514
515         default:
516                 emulate = TRUE;
517                 break;
518         }
519
520         if (emulate) {
521 #if SIZEOF_REGISTER == 8
522                 if (decompose_long_opcode (cfg, ins, &repl))
523                         emulate = FALSE;
524 #else
525                 if (COMPILE_LLVM (cfg) && decompose_long_opcode (cfg, ins, &repl))
526                         emulate = FALSE;
527 #endif
528
529                 if (emulate && mono_find_jit_opcode_emulation (ins->opcode))
530                         cfg->has_emulated_ops = TRUE;
531         }
532
533         if (ins->opcode == OP_NOP) {
534                 if (repl) {
535                         repl->type = type;
536                         return repl;
537                 } else {
538                         /* Use the last emitted instruction */
539                         ins = cfg->cbb->last_ins;
540                         g_assert (ins);
541                         ins->type = type;
542                         g_assert (ins->dreg == dreg);
543                         return ins;
544                 }
545         } else {
546                 return ins;
547         }
548 }
549
550 #if SIZEOF_REGISTER == 4
551 static int lbr_decomp [][2] = {
552         {0, 0}, /* BEQ */
553         {OP_IBGT, OP_IBGE_UN}, /* BGE */
554         {OP_IBGT, OP_IBGT_UN}, /* BGT */
555         {OP_IBLT, OP_IBLE_UN}, /* BLE */
556         {OP_IBLT, OP_IBLT_UN}, /* BLT */
557         {0, 0}, /* BNE_UN */
558         {OP_IBGT_UN, OP_IBGE_UN}, /* BGE_UN */
559         {OP_IBGT_UN, OP_IBGT_UN}, /* BGT_UN */
560         {OP_IBLT_UN, OP_IBLE_UN}, /* BLE_UN */
561         {OP_IBLT_UN, OP_IBLT_UN}, /* BLT_UN */
562 };
563
564 static int lcset_decomp [][2] = {
565         {0, 0}, /* CEQ */
566         {OP_IBLT, OP_IBLE_UN}, /* CGT */
567         {OP_IBLT_UN, OP_IBLE_UN}, /* CGT_UN */
568         {OP_IBGT, OP_IBGE_UN}, /* CLT */
569         {OP_IBGT_UN, OP_IBGE_UN}, /* CLT_UN */
570 };
571 #endif
572
573 /**
574  * mono_decompose_long_opts:
575  *
576  *  Decompose 64bit opcodes into 32bit opcodes on 32 bit platforms.
577  */
578 void
579 mono_decompose_long_opts (MonoCompile *cfg)
580 {
581 #if SIZEOF_REGISTER == 4
582         MonoBasicBlock *bb, *first_bb;
583
584         /*
585          * Some opcodes, like lcall can't be decomposed so the rest of the JIT
586          * needs to be able to handle long vregs.
587          */
588
589         /**
590          * Create a dummy bblock and emit code into it so we can use the normal 
591          * code generation macros.
592          */
593         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
594         first_bb = cfg->cbb;
595
596         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
597                 MonoInst *tree = mono_bb_first_inst(bb, FILTER_IL_SEQ_POINT);
598                 MonoInst *prev = NULL;
599
600                    /*
601                 mono_print_bb (bb, "BEFORE LOWER_LONG_OPTS");
602                 */
603
604                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
605
606                 while (tree) {
607                         mono_arch_decompose_long_opts (cfg, tree);
608
609                         switch (tree->opcode) {
610                         case OP_I8CONST:
611                                 MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_LS (tree->dreg), tree->inst_ls_word);
612                                 MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), tree->inst_ms_word);
613                                 break;
614                         case OP_DUMMY_I8CONST:
615                                 MONO_EMIT_NEW_DUMMY_INIT (cfg, MONO_LVREG_LS (tree->dreg), OP_DUMMY_ICONST);
616                                 MONO_EMIT_NEW_DUMMY_INIT (cfg, MONO_LVREG_MS (tree->dreg), OP_DUMMY_ICONST);
617                                 break;
618                         case OP_LMOVE:
619                         case OP_LCONV_TO_U8:
620                         case OP_LCONV_TO_I8:
621                         case OP_LCONV_TO_OVF_U8_UN:
622                         case OP_LCONV_TO_OVF_I8:
623                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1));
624                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1));
625                                 break;
626                         case OP_STOREI8_MEMBASE_REG:
627                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_MS_WORD_OFFSET, MONO_LVREG_MS (tree->sreg1));
628                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_LS_WORD_OFFSET, MONO_LVREG_LS (tree->sreg1));
629                                 break;
630                         case OP_LOADI8_MEMBASE:
631                                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, MONO_LVREG_MS (tree->dreg), tree->inst_basereg, tree->inst_offset + MINI_MS_WORD_OFFSET);
632                                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, MONO_LVREG_LS (tree->dreg), tree->inst_basereg, tree->inst_offset + MINI_LS_WORD_OFFSET);
633                                 break;
634
635                         case OP_ICONV_TO_I8: {
636                                 guint32 tmpreg = alloc_ireg (cfg);
637
638                                 /* branchless code:
639                                  * low = reg;
640                                  * tmp = low > -1 ? 1: 0;
641                                  * high = tmp - 1; if low is zero or pos high becomes 0, else -1
642                                  */
643                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1);
644                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, MONO_LVREG_LS (tree->dreg), -1);
645                                 MONO_EMIT_NEW_BIALU (cfg, OP_ICGT, tmpreg, -1, -1);
646                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISUB_IMM, MONO_LVREG_MS (tree->dreg), tmpreg, 1);
647                                 break;
648                         }
649                         case OP_ICONV_TO_U8:
650                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1);
651                                 MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0);
652                                 break;
653                         case OP_ICONV_TO_OVF_I8:
654                                 /* a signed 32 bit num always fits in a signed 64 bit one */
655                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, MONO_LVREG_MS (tree->dreg), tree->sreg1, 31);
656                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1);
657                                 break;
658                         case OP_ICONV_TO_OVF_U8:
659                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1, 0);
660                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
661                                 MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0);
662                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1);
663                                 break;
664                         case OP_ICONV_TO_OVF_I8_UN:
665                         case OP_ICONV_TO_OVF_U8_UN:
666                                 /* an unsigned 32 bit num always fits in an (un)signed 64 bit one */
667                                 MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0);
668                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1);
669                                 break;
670                         case OP_LCONV_TO_I1:
671                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, MONO_LVREG_LS (tree->sreg1));
672                                 break;
673                         case OP_LCONV_TO_U1:
674                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U1, tree->dreg, MONO_LVREG_LS (tree->sreg1));
675                                 break;
676                         case OP_LCONV_TO_I2:
677                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, MONO_LVREG_LS (tree->sreg1));
678                                 break;
679                         case OP_LCONV_TO_U2:
680                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U2, tree->dreg, MONO_LVREG_LS (tree->sreg1));
681                                 break;
682                         case OP_LCONV_TO_I4:
683                         case OP_LCONV_TO_U4:
684                         case OP_LCONV_TO_I:
685                         case OP_LCONV_TO_U:
686                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, MONO_LVREG_LS (tree->sreg1));
687                                 break;
688 #ifndef MONO_ARCH_EMULATE_LCONV_TO_R8
689                         case OP_LCONV_TO_R8:
690                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R8_2, tree->dreg, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_MS (tree->sreg1));
691                                 break;
692 #endif
693 #ifndef MONO_ARCH_EMULATE_LCONV_TO_R4
694                         case OP_LCONV_TO_R4:
695                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R4_2, tree->dreg, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_MS (tree->sreg1));
696                                 break;
697 #endif
698 #ifndef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
699                         case OP_LCONV_TO_R_UN:
700                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R_UN_2, tree->dreg, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_MS (tree->sreg1));
701                                 break;
702 #endif
703                         case OP_LCONV_TO_OVF_I1: {
704                                 MonoBasicBlock *is_negative, *end_label;
705
706                                 NEW_BBLOCK (cfg, is_negative);
707                                 NEW_BBLOCK (cfg, end_label);
708
709                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
710                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
711                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), -1);
712                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
713
714                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
715                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative);
716
717                                 /* Positive */
718                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 127);
719                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
720                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label);
721
722                                 /* Negative */
723                                 MONO_START_BB (cfg, is_negative);
724                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), -128);
725                                 MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException");
726
727                                 MONO_START_BB (cfg, end_label);
728
729                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, MONO_LVREG_LS (tree->sreg1));
730                                 break;
731                         }
732                         case OP_LCONV_TO_OVF_I1_UN:
733                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
734                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
735
736                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 127);
737                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
738                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), -128);
739                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
740                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, MONO_LVREG_LS (tree->sreg1));
741                                 break;
742                         case OP_LCONV_TO_OVF_U1:
743                         case OP_LCONV_TO_OVF_U1_UN:
744                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
745                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
746
747                                 /* probe value to be within 0 to 255 */
748                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 255);
749                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
750                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, MONO_LVREG_LS (tree->sreg1), 0xff);
751                                 break;
752                         case OP_LCONV_TO_OVF_I2: {
753                                 MonoBasicBlock *is_negative, *end_label;
754
755                                 NEW_BBLOCK (cfg, is_negative);
756                                 NEW_BBLOCK (cfg, end_label);
757
758                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
759                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
760                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), -1);
761                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
762
763                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
764                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative);
765
766                                 /* Positive */
767                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 32767);
768                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
769                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label);
770
771                                 /* Negative */
772                                 MONO_START_BB (cfg, is_negative);
773                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), -32768);
774                                 MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException");
775                                 MONO_START_BB (cfg, end_label);
776
777                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, MONO_LVREG_LS (tree->sreg1));
778                                 break;
779                         }
780                         case OP_LCONV_TO_OVF_I2_UN:
781                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
782                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
783
784                                 /* Probe value to be within -32768 and 32767 */
785                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 32767);
786                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
787                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), -32768);
788                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
789                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, MONO_LVREG_LS (tree->sreg1));
790                                 break;
791                         case OP_LCONV_TO_OVF_U2:
792                         case OP_LCONV_TO_OVF_U2_UN:
793                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
794                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
795
796                                 /* Probe value to be within 0 and 65535 */
797                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 0xffff);
798                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
799                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, MONO_LVREG_LS (tree->sreg1), 0xffff);
800                                 break;
801                         case OP_LCONV_TO_OVF_I4:
802                         case OP_LCONV_TO_OVF_I:
803                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_OVF_I4_2, tree->dreg, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_MS (tree->sreg1));
804                                 break;
805                         case OP_LCONV_TO_OVF_U4:
806                         case OP_LCONV_TO_OVF_U:
807                         case OP_LCONV_TO_OVF_U4_UN:
808                         case OP_LCONV_TO_OVF_U_UN:
809                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
810                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
811                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, MONO_LVREG_LS (tree->sreg1));
812                                 break;
813                         case OP_LCONV_TO_OVF_I_UN:
814                         case OP_LCONV_TO_OVF_I4_UN:
815                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
816                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
817                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_LS (tree->sreg1), 0);
818                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
819                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, MONO_LVREG_LS (tree->sreg1));
820                                 break;
821                         case OP_LCONV_TO_OVF_U8:
822                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
823                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
824
825                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1));
826                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1));
827                                 break;
828                         case OP_LCONV_TO_OVF_I8_UN:
829                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
830                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
831
832                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1));
833                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1));
834                                 break;
835
836                         case OP_LADD:
837                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
838                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
839                                 break;
840                         case OP_LSUB:
841                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
842                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
843                                 break;
844
845                         case OP_LADD_OVF:
846                                 /* ADC sets the condition code */
847                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
848                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
849                                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
850                                 break;
851                         case OP_LADD_OVF_UN:
852                                 /* ADC sets the condition code */
853                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
854                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
855                                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
856                                 break;
857                         case OP_LSUB_OVF:
858                                 /* SBB sets the condition code */
859                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
860                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
861                                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
862                                 break;
863                         case OP_LSUB_OVF_UN:
864                                 /* SBB sets the condition code */
865                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
866                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
867                                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
868                                 break;
869                         case OP_LAND:
870                                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
871                                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
872                                 break;
873                         case OP_LOR:
874                                 MONO_EMIT_NEW_BIALU (cfg, OP_IOR, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
875                                 MONO_EMIT_NEW_BIALU (cfg, OP_IOR, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
876                                 break;
877                         case OP_LXOR:
878                                 MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
879                                 MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
880                                 break;
881                         case OP_LNOT:
882                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1));
883                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1));
884                                 break;
885                         case OP_LNEG:
886                                 /* Handled in mono_arch_decompose_long_opts () */
887                                 g_assert_not_reached ();
888                                 break;
889                         case OP_LMUL:
890                                 /* Emulated */
891                                 /* FIXME: Add OP_BIGMUL optimization */
892                                 break;
893
894                         case OP_LADD_IMM:
895                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADDCC_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word);
896                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word);
897                                 break;
898                         case OP_LSUB_IMM:
899                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUBCC_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word);
900                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SBB_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word);
901                                 break;
902                         case OP_LAND_IMM:
903                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word);
904                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word);
905                                 break;
906                         case OP_LOR_IMM:
907                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word);
908                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word);
909                                 break;
910                         case OP_LXOR_IMM:
911                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word);
912                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word);
913                                 break;
914                         case OP_LSHR_UN_IMM:
915                                 if (tree->inst_c1 == 32) {
916
917                                         /* The original code had this comment: */
918                                         /* special case that gives a nice speedup and happens to workaorund a ppc jit but (for the release)
919                                          * later apply the speedup to the left shift as well
920                                          * See BUG# 57957.
921                                          */
922                                         /* FIXME: Move this to the strength reduction pass */
923                                         /* just move the upper half to the lower and zero the high word */
924                                         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), MONO_LVREG_MS (tree->sreg1));
925                                         MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0);
926                                 }
927                                 break;
928                         case OP_LSHL_IMM:
929                                 if (tree->inst_c1 == 32) {
930                                         /* just move the lower half to the upper and zero the lower word */
931                                         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (tree->dreg), MONO_LVREG_LS (tree->sreg1));
932                                         MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_LS (tree->dreg), 0);
933                                 }
934                                 break;
935
936                         case OP_LCOMPARE: {
937                                 MonoInst *next = mono_inst_next (tree, FILTER_IL_SEQ_POINT);
938
939                                 g_assert (next);
940
941                                 switch (next->opcode) {
942                                 case OP_LBEQ:
943                                 case OP_LBNE_UN: {
944                                         int d1, d2;
945
946                                         /* Branchless version based on gcc code */
947                                         d1 = alloc_ireg (cfg);
948                                         d2 = alloc_ireg (cfg);
949                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
950                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
951                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
952                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
953                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
954                                         NULLIFY_INS (next);
955                                         break;
956                                 }
957                                 case OP_LBGE:
958                                 case OP_LBGT:
959                                 case OP_LBLE:
960                                 case OP_LBLT:
961                                 case OP_LBGE_UN:
962                                 case OP_LBGT_UN:
963                                 case OP_LBLE_UN:
964                                 case OP_LBLT_UN:
965                                         /* Convert into three comparisons + branches */
966                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
967                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lbr_decomp [next->opcode - OP_LBEQ][0], next->inst_true_bb);
968                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
969                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
970                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
971                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
972                                         NULLIFY_INS (next);
973                                         break;
974                                 case OP_LCEQ: {
975                                         int d1, d2;
976         
977                                         /* Branchless version based on gcc code */
978                                         d1 = alloc_ireg (cfg);
979                                         d2 = alloc_ireg (cfg);
980                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
981                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
982                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
983
984                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
985                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
986                                         NULLIFY_INS (next);
987                                         break;
988                                 }
989                                 case OP_LCLT:
990                                 case OP_LCLT_UN:
991                                 case OP_LCGT:
992                                 case OP_LCGT_UN: {
993                                         MonoBasicBlock *set_to_0, *set_to_1;
994         
995                                         NEW_BBLOCK (cfg, set_to_0);
996                                         NEW_BBLOCK (cfg, set_to_1);
997
998                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 0);
999                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
1000                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][0], set_to_0);
1001                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
1002                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, set_to_1);
1003                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
1004                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][1], set_to_0);
1005                                         MONO_START_BB (cfg, set_to_1);
1006                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
1007                                         MONO_START_BB (cfg, set_to_0);
1008                                         NULLIFY_INS (next);
1009                                         break;  
1010                                 }
1011                                 default:
1012                                         g_assert_not_reached ();
1013                                 }
1014                                 break;
1015                         }
1016
1017                         /* Not yet used, since lcompare is decomposed before local cprop */
1018                         case OP_LCOMPARE_IMM: {
1019                                 MonoInst *next = mono_inst_next (tree, FILTER_IL_SEQ_POINT);
1020                                 guint32 low_imm = tree->inst_ls_word;
1021                                 guint32 high_imm = tree->inst_ms_word;
1022                                 int low_reg = MONO_LVREG_LS (tree->sreg1);
1023                                 int high_reg = MONO_LVREG_MS (tree->sreg1);
1024
1025                                 g_assert (next);
1026
1027                                 switch (next->opcode) {
1028                                 case OP_LBEQ:
1029                                 case OP_LBNE_UN: {
1030                                         int d1, d2;
1031
1032                                         /* Branchless version based on gcc code */
1033                                         d1 = alloc_ireg (cfg);
1034                                         d2 = alloc_ireg (cfg);
1035                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d1, low_reg, low_imm);
1036                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d2, high_reg, high_imm);
1037                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
1038                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
1039                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
1040                                         NULLIFY_INS (next);
1041                                         break;
1042                                 }
1043
1044                                 case OP_LBGE:
1045                                 case OP_LBGT:
1046                                 case OP_LBLE:
1047                                 case OP_LBLT:
1048                                 case OP_LBGE_UN:
1049                                 case OP_LBGT_UN:
1050                                 case OP_LBLE_UN:
1051                                 case OP_LBLT_UN:
1052                                         /* Convert into three comparisons + branches */
1053                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1054                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lbr_decomp [next->opcode - OP_LBEQ][0], next->inst_true_bb);
1055                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1056                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
1057                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
1058                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
1059                                         NULLIFY_INS (next);
1060                                         break;
1061                                 case OP_LCEQ: {
1062                                         int d1, d2;
1063         
1064                                         /* Branchless version based on gcc code */
1065                                         d1 = alloc_ireg (cfg);
1066                                         d2 = alloc_ireg (cfg);
1067                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d1, low_reg, low_imm);
1068                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d2, high_reg, high_imm);
1069                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
1070
1071                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
1072                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
1073                                         NULLIFY_INS (next);
1074                                         break;
1075                                 }
1076                                 case OP_LCLT:
1077                                 case OP_LCLT_UN:
1078                                 case OP_LCGT:
1079                                 case OP_LCGT_UN: {
1080                                         MonoBasicBlock *set_to_0, *set_to_1;
1081         
1082                                         NEW_BBLOCK (cfg, set_to_0);
1083                                         NEW_BBLOCK (cfg, set_to_1);
1084
1085                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 0);
1086                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1087                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][0], set_to_0);
1088                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1089                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, set_to_1);
1090                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
1091                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][1], set_to_0);
1092                                         MONO_START_BB (cfg, set_to_1);
1093                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
1094                                         MONO_START_BB (cfg, set_to_0);
1095                                         NULLIFY_INS (next);
1096                                         break;  
1097                                 }
1098                                 default:
1099                                         g_assert_not_reached ();
1100                                 }
1101                                 break;
1102                         }
1103
1104                         default:
1105                                 break;
1106                         }
1107
1108                         if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1109                                 MonoInst *new_prev;
1110
1111                                 /* Replace the original instruction with the new code sequence */
1112
1113                                 /* Ignore the new value of prev */
1114                                 new_prev = prev;
1115                                 mono_replace_ins (cfg, bb, tree, &new_prev, first_bb, cfg->cbb);
1116
1117                                 /* Process the newly added ops again since they can be long ops too */
1118                                 if (prev)
1119                                         tree = mono_inst_next (prev, FILTER_IL_SEQ_POINT);
1120                                 else
1121                                         tree = mono_bb_first_inst (bb, FILTER_IL_SEQ_POINT);
1122
1123                                 first_bb->code = first_bb->last_ins = NULL;
1124                                 first_bb->in_count = first_bb->out_count = 0;
1125                                 cfg->cbb = first_bb;
1126                         }
1127                         else {
1128                                 prev = tree;
1129                                 tree = mono_inst_next (tree, FILTER_IL_SEQ_POINT);
1130                         }
1131                 }
1132         }
1133 #endif
1134
1135         /*
1136         for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
1137                 mono_print_bb (bb, "AFTER LOWER-LONG-OPTS");
1138         */
1139 }
1140
1141 /**
1142  * mono_decompose_vtype_opts:
1143  *
1144  *  Decompose valuetype opcodes.
1145  */
1146 void
1147 mono_decompose_vtype_opts (MonoCompile *cfg)
1148 {
1149         MonoBasicBlock *bb, *first_bb;
1150
1151         /**
1152          * Using OP_V opcodes and decomposing them later have two main benefits:
1153          * - it simplifies method_to_ir () since there is no need to special-case vtypes
1154          *   everywhere.
1155          * - it gets rid of the LDADDR opcodes generated when vtype operations are decomposed,
1156          *   enabling optimizations to work on vtypes too.
1157          * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it 
1158          * can be executed anytime. It should be executed as late as possible so vtype
1159          * opcodes can be optimized by the other passes.
1160          * The pinvoke wrappers need to manipulate vtypes in their unmanaged representation.
1161          * This is indicated by setting the 'backend.is_pinvoke' field of the MonoInst for the 
1162          * var to 1.
1163          * This is done on demand, ie. by the LDNATIVEOBJ opcode, and propagated by this pass 
1164          * when OP_VMOVE opcodes are decomposed.
1165          */
1166
1167         /* 
1168          * Vregs have no associated type information, so we store the type of the vregs
1169          * in ins->klass.
1170          */
1171
1172         /**
1173          * Create a dummy bblock and emit code into it so we can use the normal 
1174          * code generation macros.
1175          */
1176         cfg->cbb = (MonoBasicBlock *)mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1177         first_bb = cfg->cbb;
1178
1179         /* For LLVM, decompose only the OP_STOREV_MEMBASE opcodes, which need write barriers and the gsharedvt opcodes */
1180
1181         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1182                 MonoInst *ins;
1183                 MonoInst *prev = NULL;
1184                 MonoInst *src_var, *dest_var, *src, *dest;
1185                 gboolean restart;
1186                 int dreg;
1187
1188                 if (cfg->verbose_level > 2) mono_print_bb (bb, "BEFORE LOWER-VTYPE-OPTS ");
1189
1190                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1191                 restart = TRUE;
1192
1193                 while (restart) {
1194                         restart = FALSE;
1195
1196                         for (ins = bb->code; ins; ins = ins->next) {
1197                                 switch (ins->opcode) {
1198                                 case OP_VMOVE: {
1199                                         g_assert (ins->klass);
1200                                         if (COMPILE_LLVM (cfg) && !mini_is_gsharedvt_klass (ins->klass))
1201                                                 break;
1202                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1203                                         dest_var = get_vreg_to_inst (cfg, ins->dreg);
1204
1205                                         if (!src_var)
1206                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1207
1208                                         if (!dest_var)
1209                                                 dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1210
1211                                         // FIXME:
1212                                         if (src_var->backend.is_pinvoke)
1213                                                 dest_var->backend.is_pinvoke = 1;
1214
1215                                         EMIT_NEW_VARLOADA ((cfg), (src), src_var, src_var->inst_vtype);
1216                                         EMIT_NEW_VARLOADA ((cfg), (dest), dest_var, dest_var->inst_vtype);
1217
1218                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1219                                         break;
1220                                 }
1221                                 case OP_VZERO:
1222                                         if (COMPILE_LLVM (cfg) && !mini_is_gsharedvt_klass (ins->klass))
1223                                                 break;
1224
1225                                         g_assert (ins->klass);
1226
1227                                         EMIT_NEW_VARLOADA_VREG (cfg, dest, ins->dreg, &ins->klass->byval_arg);
1228                                         mini_emit_initobj (cfg, dest, NULL, ins->klass);
1229                                         
1230                                         if (cfg->compute_gc_maps) {
1231                                                 MonoInst *tmp;
1232
1233                                                 /* 
1234                                                  * Tell the GC map code that the vtype is considered live after
1235                                                  * the initialization.
1236                                                  */
1237                                                 MONO_INST_NEW (cfg, tmp, OP_GC_LIVENESS_DEF);
1238                                                 tmp->inst_c1 = ins->dreg;
1239                                                 MONO_ADD_INS (cfg->cbb, tmp);
1240                                         }
1241                                         break;
1242                                 case OP_DUMMY_VZERO:
1243                                         if (COMPILE_LLVM (cfg))
1244                                                 break;
1245
1246                                         NULLIFY_INS (ins);
1247                                         break;
1248                                 case OP_STOREV_MEMBASE: {
1249                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1250
1251                                         if (!src_var) {
1252                                                 g_assert (ins->klass);
1253                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1254                                         }
1255
1256                                         EMIT_NEW_VARLOADA_VREG ((cfg), (src), ins->sreg1, &ins->klass->byval_arg);
1257
1258                                         dreg = alloc_preg (cfg);
1259                                         EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
1260                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1261                                         break;
1262                                 }
1263                                 case OP_LOADV_MEMBASE: {
1264                                         g_assert (ins->klass);
1265                                         if (COMPILE_LLVM (cfg) && !mini_is_gsharedvt_klass (ins->klass))
1266                                                 break;
1267
1268                                         dest_var = get_vreg_to_inst (cfg, ins->dreg);
1269                                         // FIXME-VT:
1270                                         // FIXME:
1271                                         if (!dest_var)
1272                                                 dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1273
1274                                         dreg = alloc_preg (cfg);
1275                                         EMIT_NEW_BIALU_IMM (cfg, src, OP_ADD_IMM, dreg, ins->inst_basereg, ins->inst_offset);
1276                                         EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
1277                                         mini_emit_stobj (cfg, dest, src, dest_var->klass, dest_var->backend.is_pinvoke);
1278                                         break;
1279                                 }
1280                                 case OP_OUTARG_VT: {
1281                                         if (COMPILE_LLVM (cfg))
1282                                                 break;
1283
1284                                         g_assert (ins->klass);
1285
1286                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1287                                         if (!src_var)
1288                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1289                                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
1290
1291                                         mono_arch_emit_outarg_vt (cfg, ins, src);
1292
1293                                         /* This might be decomposed into other vtype opcodes */
1294                                         restart = TRUE;
1295                                         break;
1296                                 }
1297                                 case OP_OUTARG_VTRETADDR: {
1298                                         MonoCallInst *call = (MonoCallInst*)ins->inst_p1;
1299
1300                                         src_var = get_vreg_to_inst (cfg, call->inst.dreg);
1301                                         if (!src_var)
1302                                                 src_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
1303                                         // FIXME: src_var->backend.is_pinvoke ?
1304
1305                                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
1306                                         src->dreg = ins->dreg;
1307                                         break;
1308                                 }
1309                                 case OP_VCALL:
1310                                 case OP_VCALL_REG:
1311                                 case OP_VCALL_MEMBASE: {
1312                                         MonoCallInst *call = (MonoCallInst*)ins;
1313                                         int size;
1314
1315                                         if (COMPILE_LLVM (cfg))
1316                                                 break;
1317
1318                                         if (call->vret_in_reg) {
1319                                                 MonoCallInst *call2;
1320
1321                                                 /* Replace the vcall with a scalar call */
1322                                                 MONO_INST_NEW_CALL (cfg, call2, OP_NOP);
1323                                                 memcpy (call2, call, sizeof (MonoCallInst));
1324                                                 switch (ins->opcode) {
1325                                                 case OP_VCALL:
1326                                                         call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL : OP_CALL;
1327                                                         break;
1328                                                 case OP_VCALL_REG:
1329                                                         call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_REG : OP_CALL_REG;
1330                                                         break;
1331                                                 case OP_VCALL_MEMBASE:
1332                                                         call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_MEMBASE : OP_CALL_MEMBASE;
1333                                                         break;
1334                                                 }
1335                                                 call2->inst.dreg = alloc_preg (cfg);
1336                                                 MONO_ADD_INS (cfg->cbb, ((MonoInst*)call2));
1337
1338                                                 /* Compute the vtype location */
1339                                                 dest_var = get_vreg_to_inst (cfg, call->inst.dreg);
1340                                                 if (!dest_var)
1341                                                         dest_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
1342                                                 EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
1343
1344                                                 /* Save the result */
1345                                                 if (dest_var->backend.is_pinvoke)
1346                                                         size = mono_class_native_size (mono_class_from_mono_type (dest_var->inst_vtype), NULL);
1347                                                 else
1348                                                         size = mono_type_size (dest_var->inst_vtype, NULL);
1349                                                 switch (size) {
1350                                                 case 1:
1351                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1352                                                         break;
1353                                                 case 2:
1354                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1355                                                         break;
1356                                                 case 3:
1357                                                 case 4:
1358                                                         if (call->vret_in_reg_fp)
1359                                                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1360                                                         else
1361                                                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1362                                                         break;
1363                                                 case 5:
1364                                                 case 6:
1365                                                 case 7:
1366                                                 case 8:
1367                                                         if (call->vret_in_reg_fp) {
1368                                                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1369                                                                 break;
1370                                                         }
1371 #if SIZEOF_REGISTER == 4
1372                                                         /*
1373                                                         FIXME Other ABIs might return in different regs than the ones used for LCALL.
1374                                                         FIXME It would be even nicer to be able to leverage the long decompose stuff.
1375                                                         */
1376                                                         switch (call2->inst.opcode) {
1377                                                         case OP_CALL:
1378                                                                 call2->inst.opcode = OP_LCALL;
1379                                                                 break;
1380                                                         case OP_CALL_REG:
1381                                                                 call2->inst.opcode = OP_LCALL_REG;
1382                                                                 break;
1383                                                         case OP_CALL_MEMBASE:
1384                                                                 call2->inst.opcode = OP_LCALL_MEMBASE;
1385                                                                 break;
1386                                                         }
1387                                                         call2->inst.dreg = alloc_lreg (cfg);
1388                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_MS_WORD_OFFSET, MONO_LVREG_MS (call2->inst.dreg));
1389                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_LS_WORD_OFFSET, MONO_LVREG_LS (call2->inst.dreg));
1390 #else
1391                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1392 #endif
1393                                                         break;
1394                                                 default:
1395                                                         /* This assumes the vtype is sizeof (gpointer) long */
1396                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1397                                                         break;
1398                                                 }
1399                                         } else {
1400                                                 switch (ins->opcode) {
1401                                                 case OP_VCALL:
1402                                                         ins->opcode = OP_VCALL2;
1403                                                         break;
1404                                                 case OP_VCALL_REG:
1405                                                         ins->opcode = OP_VCALL2_REG;
1406                                                         break;
1407                                                 case OP_VCALL_MEMBASE:
1408                                                         ins->opcode = OP_VCALL2_MEMBASE;
1409                                                         break;
1410                                                 }
1411                                                 ins->dreg = -1;
1412                                         }
1413                                         break;
1414                                 }
1415                                 default:
1416                                         break;
1417                                 }
1418
1419                                 g_assert (cfg->cbb == first_bb);
1420
1421                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1422                                         /* Replace the original instruction with the new code sequence */
1423
1424                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1425                                         first_bb->code = first_bb->last_ins = NULL;
1426                                         first_bb->in_count = first_bb->out_count = 0;
1427                                         cfg->cbb = first_bb;
1428                                 }
1429                                 else
1430                                         prev = ins;
1431                         }
1432                 }
1433
1434                 if (cfg->verbose_level > 2) mono_print_bb (bb, "AFTER LOWER-VTYPE-OPTS ");
1435         }
1436 }
1437
1438 inline static MonoInst *
1439 mono_get_domainvar (MonoCompile *cfg)
1440 {
1441         if (!cfg->domainvar)
1442                 cfg->domainvar = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
1443         return cfg->domainvar;
1444 }
1445
1446 /**
1447  * mono_decompose_array_access_opts:
1448  *
1449  *  Decompose array access opcodes.
1450  */
1451 void
1452 mono_decompose_array_access_opts (MonoCompile *cfg)
1453 {
1454         MonoBasicBlock *bb, *first_bb;
1455
1456         /*
1457          * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it 
1458          * can be executed anytime. It should be run before decompose_long
1459          */
1460
1461         /**
1462          * Create a dummy bblock and emit code into it so we can use the normal 
1463          * code generation macros.
1464          */
1465         cfg->cbb = (MonoBasicBlock *)mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1466         first_bb = cfg->cbb;
1467
1468         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1469                 MonoInst *ins;
1470                 MonoInst *prev = NULL;
1471                 MonoInst *dest;
1472                 MonoInst *iargs [3];
1473                 gboolean restart;
1474
1475                 if (!bb->has_array_access)
1476                         continue;
1477
1478                 if (cfg->verbose_level > 3) mono_print_bb (bb, "BEFORE DECOMPOSE-ARRAY-ACCESS-OPTS ");
1479
1480                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1481                 restart = TRUE;
1482
1483                 while (restart) {
1484                         restart = FALSE;
1485
1486                         for (ins = bb->code; ins; ins = ins->next) {
1487                                 switch (ins->opcode) {
1488                                 case OP_LDLEN:
1489                                         NEW_LOAD_MEMBASE_FLAGS (cfg, dest, OP_LOADI4_MEMBASE, ins->dreg, ins->sreg1,
1490                                                                                         MONO_STRUCT_OFFSET (MonoArray, max_length), ins->flags | MONO_INST_INVARIANT_LOAD);
1491                                         MONO_ADD_INS (cfg->cbb, dest);
1492                                         break;
1493                                 case OP_BOUNDS_CHECK:
1494                                         MONO_EMIT_NULL_CHECK (cfg, ins->sreg1);
1495                                         if (COMPILE_LLVM (cfg))
1496                                                 MONO_EMIT_DEFAULT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2, ins->flags & MONO_INST_FAULT);
1497                                         else
1498                                                 MONO_ARCH_EMIT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2);
1499                                         break;
1500                                 case OP_NEWARR:
1501                                         if (cfg->opt & MONO_OPT_SHARED) {
1502                                                 EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
1503                                                 EMIT_NEW_CLASSCONST (cfg, iargs [1], ins->inst_newa_class);
1504                                                 MONO_INST_NEW (cfg, iargs [2], OP_MOVE);
1505                                                 iargs [2]->dreg = ins->sreg1;
1506
1507                                                 dest = mono_emit_jit_icall (cfg, mono_array_new, iargs);
1508                                                 dest->dreg = ins->dreg;
1509                                         } else {
1510                                                 MonoClass *array_class = mono_array_class_get (ins->inst_newa_class, 1);
1511                                                 MonoVTable *vtable = mono_class_vtable (cfg->domain, array_class);
1512                                                 MonoMethod *managed_alloc = mono_gc_get_managed_array_allocator (array_class);
1513
1514                                                 g_assert (vtable); /*This shall not fail since we check for this condition on OP_NEWARR creation*/
1515                                                 NEW_VTABLECONST (cfg, iargs [0], vtable);
1516                                                 MONO_ADD_INS (cfg->cbb, iargs [0]);
1517                                                 MONO_INST_NEW (cfg, iargs [1], OP_MOVE);
1518                                                 iargs [1]->dreg = ins->sreg1;
1519
1520                                                 if (managed_alloc)
1521                                                         dest = mono_emit_method_call (cfg, managed_alloc, iargs, NULL);
1522                                                 else
1523                                                         dest = mono_emit_jit_icall (cfg, ves_icall_array_new_specific, iargs);
1524                                                 dest->dreg = ins->dreg;
1525                                         }
1526                                         break;
1527                                 case OP_STRLEN:
1528                                         MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS (cfg, OP_LOADI4_MEMBASE, ins->dreg,
1529                                                                                                                  ins->sreg1, MONO_STRUCT_OFFSET (MonoString, length), ins->flags | MONO_INST_INVARIANT_LOAD);
1530                                         break;
1531                                 default:
1532                                         break;
1533                                 }
1534
1535                                 g_assert (cfg->cbb == first_bb);
1536
1537                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1538                                         /* Replace the original instruction with the new code sequence */
1539
1540                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1541                                         first_bb->code = first_bb->last_ins = NULL;
1542                                         first_bb->in_count = first_bb->out_count = 0;
1543                                         cfg->cbb = first_bb;
1544                                 }
1545                                 else
1546                                         prev = ins;
1547                         }
1548                 }
1549
1550                 if (cfg->verbose_level > 3) mono_print_bb (bb, "AFTER DECOMPOSE-ARRAY-ACCESS-OPTS ");
1551         }
1552 }
1553
1554 typedef union {
1555         guint32 vali [2];
1556         gint64 vall;
1557         double vald;
1558 } DVal;
1559
1560 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
1561
1562 /**
1563  * mono_decompose_soft_float:
1564  *
1565  *  Soft float support on ARM. We store each double value in a pair of integer vregs,
1566  * similar to long support on 32 bit platforms. 32 bit float values require special
1567  * handling when used as locals, arguments, and in calls.
1568  * One big problem with soft-float is that there are few r4 test cases in our test suite.
1569  */
1570 void
1571 mono_decompose_soft_float (MonoCompile *cfg)
1572 {
1573         MonoBasicBlock *bb, *first_bb;
1574
1575         /*
1576          * This pass creates long opcodes, so it should be run before decompose_long_opts ().
1577          */
1578
1579         /**
1580          * Create a dummy bblock and emit code into it so we can use the normal 
1581          * code generation macros.
1582          */
1583         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1584         first_bb = cfg->cbb;
1585
1586         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1587                 MonoInst *ins;
1588                 MonoInst *prev = NULL;
1589                 gboolean restart;
1590
1591                 if (cfg->verbose_level > 3) mono_print_bb (bb, "BEFORE HANDLE-SOFT-FLOAT ");
1592
1593                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1594                 restart = TRUE;
1595
1596                 while (restart) {
1597                         restart = FALSE;
1598
1599                         for (ins = bb->code; ins; ins = ins->next) {
1600                                 const char *spec = INS_INFO (ins->opcode);
1601
1602                                 /* Most fp operations are handled automatically by opcode emulation */
1603
1604                                 switch (ins->opcode) {
1605                                 case OP_R8CONST: {
1606                                         DVal d;
1607                                         d.vald = *(double*)ins->inst_p0;
1608                                         MONO_EMIT_NEW_I8CONST (cfg, ins->dreg, d.vall);
1609                                         break;
1610                                 }
1611                                 case OP_R4CONST: {
1612                                         DVal d;
1613                                         /* We load the r8 value */
1614                                         d.vald = *(float*)ins->inst_p0;
1615                                         MONO_EMIT_NEW_I8CONST (cfg, ins->dreg, d.vall);
1616                                         break;
1617                                 }
1618                                 case OP_FMOVE:
1619                                         ins->opcode = OP_LMOVE;
1620                                         break;
1621                                 case OP_FGETLOW32:
1622                                         ins->opcode = OP_MOVE;
1623                                         ins->sreg1 = MONO_LVREG_LS (ins->sreg1);
1624                                         break;
1625                                 case OP_FGETHIGH32:
1626                                         ins->opcode = OP_MOVE;
1627                                         ins->sreg1 = MONO_LVREG_MS (ins->sreg1);
1628                                         break;
1629                                 case OP_SETFRET: {
1630                                         int reg = ins->sreg1;
1631
1632                                         ins->opcode = OP_SETLRET;
1633                                         ins->dreg = -1;
1634                                         ins->sreg1 = MONO_LVREG_LS (reg);
1635                                         ins->sreg2 = MONO_LVREG_MS (reg);
1636                                         break;
1637                                 }
1638                                 case OP_LOADR8_MEMBASE:
1639                                         ins->opcode = OP_LOADI8_MEMBASE;
1640                                         break;
1641                                 case OP_STORER8_MEMBASE_REG:
1642                                         ins->opcode = OP_STOREI8_MEMBASE_REG;
1643                                         break;
1644                                 case OP_STORER4_MEMBASE_REG: {
1645                                         MonoInst *iargs [2];
1646                                         int addr_reg;
1647
1648                                         /* Arg 1 is the double value */
1649                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1650                                         iargs [0]->dreg = ins->sreg1;
1651
1652                                         /* Arg 2 is the address to store to */
1653                                         addr_reg = mono_alloc_preg (cfg);
1654                                         EMIT_NEW_BIALU_IMM (cfg, iargs [1], OP_PADD_IMM, addr_reg, ins->inst_destbasereg, ins->inst_offset);
1655                                         mono_emit_jit_icall (cfg, mono_fstore_r4, iargs);
1656                                         restart = TRUE;
1657                                         break;
1658                                 }
1659                                 case OP_LOADR4_MEMBASE: {
1660                                         MonoInst *iargs [1];
1661                                         MonoInst *conv;
1662                                         int addr_reg;
1663
1664                                         addr_reg = mono_alloc_preg (cfg);
1665                                         EMIT_NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, addr_reg, ins->inst_basereg, ins->inst_offset);
1666                                         conv = mono_emit_jit_icall (cfg, mono_fload_r4, iargs);
1667                                         conv->dreg = ins->dreg;
1668                                         break;
1669                                 }                                       
1670                                 case OP_FCALL:
1671                                 case OP_FCALL_REG:
1672                                 case OP_FCALL_MEMBASE: {
1673                                         MonoCallInst *call = (MonoCallInst*)ins;
1674                                         if (call->signature->ret->type == MONO_TYPE_R4) {
1675                                                 MonoCallInst *call2;
1676                                                 MonoInst *iargs [1];
1677                                                 MonoInst *conv;
1678                                                 GSList *l;
1679
1680                                                 /* Convert the call into a call returning an int */
1681                                                 MONO_INST_NEW_CALL (cfg, call2, OP_CALL);
1682                                                 memcpy (call2, call, sizeof (MonoCallInst));
1683                                                 switch (ins->opcode) {
1684                                                 case OP_FCALL:
1685                                                         call2->inst.opcode = OP_CALL;
1686                                                         break;
1687                                                 case OP_FCALL_REG:
1688                                                         call2->inst.opcode = OP_CALL_REG;
1689                                                         break;
1690                                                 case OP_FCALL_MEMBASE:
1691                                                         call2->inst.opcode = OP_CALL_MEMBASE;
1692                                                         break;
1693                                                 default:
1694                                                         g_assert_not_reached ();
1695                                                 }
1696                                                 call2->inst.dreg = mono_alloc_ireg (cfg);
1697                                                 MONO_ADD_INS (cfg->cbb, (MonoInst*)call2);
1698
1699                                                 /* Remap OUTARG_VT instructions referencing this call */
1700                                                 for (l = call->outarg_vts; l; l = l->next)
1701                                                         ((MonoInst*)(l->data))->inst_p0 = call2;
1702
1703                                                 /* FIXME: Optimize this */
1704
1705                                                 /* Emit an r4->r8 conversion */
1706                                                 EMIT_NEW_VARLOADA_VREG (cfg, iargs [0], call2->inst.dreg, &mono_defaults.int32_class->byval_arg);
1707                                                 conv = mono_emit_jit_icall (cfg, mono_fload_r4, iargs);
1708                                                 conv->dreg = ins->dreg;
1709
1710                                                 /* The call sequence might include fp ins */
1711                                                 restart = TRUE;
1712                                         } else {
1713                                                 switch (ins->opcode) {
1714                                                 case OP_FCALL:
1715                                                         ins->opcode = OP_LCALL;
1716                                                         break;
1717                                                 case OP_FCALL_REG:
1718                                                         ins->opcode = OP_LCALL_REG;
1719                                                         break;
1720                                                 case OP_FCALL_MEMBASE:
1721                                                         ins->opcode = OP_LCALL_MEMBASE;
1722                                                         break;
1723                                                 default:
1724                                                         g_assert_not_reached ();
1725                                                 }
1726                                         }
1727                                         break;
1728                                 }
1729                                 case OP_FCOMPARE: {
1730                                         MonoJitICallInfo *info;
1731                                         MonoInst *iargs [2];
1732                                         MonoInst *call, *cmp, *br;
1733
1734                                         /* Convert fcompare+fbcc to icall+icompare+beq */
1735
1736                                         if (!ins->next) {
1737                                                 /* The branch might be optimized away */
1738                                                 NULLIFY_INS (ins);
1739                                                 break;
1740                                         }
1741
1742                                         info = mono_find_jit_opcode_emulation (ins->next->opcode);
1743                                         if (!info) {
1744                                                 /* The branch might be optimized away */
1745                                                 NULLIFY_INS (ins);
1746                                                 break;
1747                                         }
1748
1749                                         /* Create dummy MonoInst's for the arguments */
1750                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1751                                         iargs [0]->dreg = ins->sreg1;
1752                                         MONO_INST_NEW (cfg, iargs [1], OP_ARG);
1753                                         iargs [1]->dreg = ins->sreg2;
1754
1755                                         call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, iargs);
1756
1757                                         MONO_INST_NEW (cfg, cmp, OP_ICOMPARE_IMM);
1758                                         cmp->sreg1 = call->dreg;
1759                                         cmp->inst_imm = 0;
1760                                         MONO_ADD_INS (cfg->cbb, cmp);
1761                                         
1762                                         MONO_INST_NEW (cfg, br, OP_IBNE_UN);
1763                                         br->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof (gpointer) * 2);
1764                                         br->inst_true_bb = ins->next->inst_true_bb;
1765                                         br->inst_false_bb = ins->next->inst_false_bb;
1766                                         MONO_ADD_INS (cfg->cbb, br);
1767
1768                                         /* The call sequence might include fp ins */
1769                                         restart = TRUE;
1770
1771                                         /* Skip fbcc or fccc */
1772                                         NULLIFY_INS (ins->next);
1773                                         break;
1774                                 }
1775                                 case OP_FCEQ:
1776                                 case OP_FCGT:
1777                                 case OP_FCGT_UN:
1778                                 case OP_FCLT:
1779                                 case OP_FCLT_UN: {
1780                                         MonoJitICallInfo *info;
1781                                         MonoInst *iargs [2];
1782                                         MonoInst *call;
1783
1784                                         /* Convert fccc to icall+icompare+iceq */
1785
1786                                         info = mono_find_jit_opcode_emulation (ins->opcode);
1787                                         g_assert (info);
1788
1789                                         /* Create dummy MonoInst's for the arguments */
1790                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1791                                         iargs [0]->dreg = ins->sreg1;
1792                                         MONO_INST_NEW (cfg, iargs [1], OP_ARG);
1793                                         iargs [1]->dreg = ins->sreg2;
1794
1795                                         call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, iargs);
1796
1797                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, call->dreg, 1);
1798                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, ins->dreg, -1);
1799
1800                                         /* The call sequence might include fp ins */
1801                                         restart = TRUE;
1802                                         break;
1803                                 }
1804                                 case OP_CKFINITE: {
1805                                         MonoInst *iargs [2];
1806                                         MonoInst *call, *cmp;
1807
1808                                         /* Convert to icall+icompare+cond_exc+move */
1809
1810                                         /* Create dummy MonoInst's for the arguments */
1811                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1812                                         iargs [0]->dreg = ins->sreg1;
1813
1814                                         call = mono_emit_jit_icall (cfg, mono_isfinite, iargs);
1815
1816                                         MONO_INST_NEW (cfg, cmp, OP_ICOMPARE_IMM);
1817                                         cmp->sreg1 = call->dreg;
1818                                         cmp->inst_imm = 1;
1819                                         MONO_ADD_INS (cfg->cbb, cmp);
1820
1821                                         MONO_EMIT_NEW_COND_EXC (cfg, INE_UN, "ArithmeticException");
1822
1823                                         /* Do the assignment if the value is finite */
1824                                         MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, ins->dreg, ins->sreg1);
1825
1826                                         restart = TRUE;
1827                                         break;
1828                                 }
1829                                 default:
1830                                         if (spec [MONO_INST_SRC1] == 'f' || spec [MONO_INST_SRC2] == 'f' || spec [MONO_INST_DEST] == 'f') {
1831                                                 mono_print_ins (ins);
1832                                                 g_assert_not_reached ();
1833                                         }
1834                                         break;
1835                                 }
1836
1837                                 g_assert (cfg->cbb == first_bb);
1838
1839                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1840                                         /* Replace the original instruction with the new code sequence */
1841
1842                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1843                                         first_bb->code = first_bb->last_ins = NULL;
1844                                         first_bb->in_count = first_bb->out_count = 0;
1845                                         cfg->cbb = first_bb;
1846                                 }
1847                                 else
1848                                         prev = ins;
1849                         }
1850                 }
1851
1852                 if (cfg->verbose_level > 3) mono_print_bb (bb, "AFTER HANDLE-SOFT-FLOAT ");
1853         }
1854
1855         mono_decompose_long_opts (cfg);
1856 }
1857
1858 #endif
1859
1860 void
1861 mono_local_emulate_ops (MonoCompile *cfg)
1862 {
1863         MonoBasicBlock *bb;
1864         gboolean inlined_wrapper = FALSE;
1865
1866         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1867                 MonoInst *ins;
1868
1869                 MONO_BB_FOR_EACH_INS (bb, ins) {
1870                         int op_noimm = mono_op_imm_to_op (ins->opcode);
1871                         MonoJitICallInfo *info;
1872
1873                         /*
1874                          * Emulation can't handle _IMM ops. If this is an imm opcode we need
1875                          * to check whether its non-imm counterpart is emulated and, if so,
1876                          * decompose it back to its non-imm counterpart.
1877                          */
1878                         if (op_noimm != -1)
1879                                 info = mono_find_jit_opcode_emulation (op_noimm);
1880                         else
1881                                 info = mono_find_jit_opcode_emulation (ins->opcode);
1882
1883                         if (info) {
1884                                 MonoInst **args;
1885                                 MonoInst *call;
1886                                 MonoBasicBlock *first_bb;
1887
1888                                 /* Create dummy MonoInst's for the arguments */
1889                                 g_assert (!info->sig->hasthis);
1890                                 g_assert (info->sig->param_count <= MONO_MAX_SRC_REGS);
1891
1892                                 if (op_noimm != -1)
1893                                         mono_decompose_op_imm (cfg, bb, ins);
1894
1895                                 args = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * info->sig->param_count);
1896                                 if (info->sig->param_count > 0) {
1897                                         int sregs [MONO_MAX_SRC_REGS];
1898                                         int num_sregs, i;
1899                                         num_sregs = mono_inst_get_src_registers (ins, sregs);
1900                                         g_assert (num_sregs == info->sig->param_count);
1901                                         for (i = 0; i < num_sregs; ++i) {
1902                                                 MONO_INST_NEW (cfg, args [i], OP_ARG);
1903                                                 args [i]->dreg = sregs [i];
1904                                         }
1905                                 }
1906
1907                                 /* We emit the call on a separate dummy basic block */
1908                                 cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1909                                 first_bb = cfg->cbb;
1910
1911                                 call = mono_emit_jit_icall_by_info (cfg, info, args);
1912                                 call->dreg = ins->dreg;
1913
1914                                 /* Replace ins with the emitted code and do the necessary bb linking */
1915                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1916                                         MonoInst *saved_prev = ins->prev;
1917
1918                                         mono_replace_ins (cfg, bb, ins, &ins->prev, first_bb, cfg->cbb);
1919                                         first_bb->code = first_bb->last_ins = NULL;
1920                                         first_bb->in_count = first_bb->out_count = 0;
1921                                         cfg->cbb = first_bb;
1922
1923                                         /* ins is hanging, continue scanning the emitted code */
1924                                         ins = saved_prev;
1925                                 } else {
1926                                         g_error ("Failed to emit emulation code");
1927                                 }
1928                                 inlined_wrapper = TRUE;
1929                         }
1930                 }
1931         }
1932
1933         /*
1934          * Avoid rerunning these passes by emitting directly the exception checkpoint
1935          * at IR level, instead of inlining the icall wrapper. FIXME
1936          */
1937         if (inlined_wrapper) {
1938                 if (!COMPILE_LLVM (cfg))
1939                         mono_decompose_long_opts (cfg);
1940                 if (cfg->opt & (MONO_OPT_CONSPROP | MONO_OPT_COPYPROP))
1941                         mono_local_cprop (cfg);
1942         }
1943 }
1944
1945 #endif /* DISABLE_JIT */