[jit] Don't decompose into unsupported instructions
[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                 cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
443                 cfg->exception_message = g_strdup_printf ("float conv.ovf.un opcodes not supported.");
444                 break;
445
446         case OP_IDIV:
447         case OP_IREM:
448         case OP_IDIV_UN:
449         case OP_IREM_UN:
450                 if (cfg->backend->emulate_div && mono_arch_opcode_needs_emulation (cfg, ins->opcode))
451                         emulate = TRUE;
452                 if (!emulate) {
453                         if (cfg->backend->need_div_check) {
454                                 int reg1 = alloc_ireg (cfg);
455                                 int reg2 = alloc_ireg (cfg);
456                                 /* b == 0 */
457                                 MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg2, 0);
458                                 MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "DivideByZeroException");
459                                 if (ins->opcode == OP_IDIV || ins->opcode == OP_IREM) {
460                                         /* b == -1 && a == 0x80000000 */
461                                         MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg2, -1);
462                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, reg1, -1);
463                                         MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0x80000000);
464                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, reg2, -1);
465                                         MONO_EMIT_NEW_BIALU (cfg, OP_IAND, reg1, reg1, reg2);
466                                         MONO_EMIT_NEW_ICOMPARE_IMM (cfg, reg1, 1);
467                                         MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "OverflowException");
468                                 }
469                         }
470                         MONO_EMIT_NEW_BIALU (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->sreg2);
471                         NULLIFY_INS (ins);
472                 }
473                 break;
474
475 #if SIZEOF_REGISTER == 8
476         case OP_LREM_IMM:
477 #endif
478         case OP_IREM_IMM: {
479                 int power = mono_is_power_of_two (ins->inst_imm);
480                 if (ins->inst_imm == 1) {
481                         ins->opcode = OP_ICONST;
482                         MONO_INST_NULLIFY_SREGS (ins);
483                         ins->inst_c0 = 0;
484 #if __s390__
485                 }
486 #else
487                 } else if ((ins->inst_imm > 0) && (ins->inst_imm < (1LL << 32)) && (power != -1)) {
488                         gboolean is_long = ins->opcode == OP_LREM_IMM;
489                         int compensator_reg = alloc_ireg (cfg);
490                         int intermediate_reg;
491
492                         /* Based on gcc code */
493
494                         /* Add compensation for negative numerators */
495
496                         if (power > 1) {
497                                 intermediate_reg = compensator_reg;
498                                 MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_ISHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31);
499                         } else {
500                                 intermediate_reg = ins->sreg1;
501                         }
502
503                         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);
504                         MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LADD : OP_IADD, ins->dreg, ins->sreg1, compensator_reg);
505                         /* Compute remainder */
506                         MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LAND_IMM : OP_AND_IMM, ins->dreg, ins->dreg, (1 << power) - 1);
507                         /* Remove compensation */
508                         MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LSUB : OP_ISUB, ins->dreg, ins->dreg, compensator_reg);
509
510                         NULLIFY_INS (ins);
511                 }
512 #endif
513                 break;
514         }
515
516         default:
517                 emulate = TRUE;
518                 break;
519         }
520
521         if (emulate) {
522                 MonoJitICallInfo *info = NULL;
523
524 #if SIZEOF_REGISTER == 8
525                 if (decompose_long_opcode (cfg, ins, &repl))
526                         emulate = FALSE;
527 #else
528                 if (COMPILE_LLVM (cfg) && decompose_long_opcode (cfg, ins, &repl))
529                         emulate = FALSE;
530 #endif
531
532                 if (emulate)
533                         info = mono_find_jit_opcode_emulation (ins->opcode);
534                 if (info) {
535                         MonoInst **args;
536                         MonoInst *call;
537
538                         /* Create dummy MonoInst's for the arguments */
539                         g_assert (!info->sig->hasthis);
540                         g_assert (info->sig->param_count <= MONO_MAX_SRC_REGS);
541
542                         args = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * info->sig->param_count);
543                         if (info->sig->param_count > 0) {
544                                 int sregs [MONO_MAX_SRC_REGS];
545                                 int num_sregs, i;
546                                 num_sregs = mono_inst_get_src_registers (ins, sregs);
547                                 g_assert (num_sregs == info->sig->param_count);
548                                 for (i = 0; i < num_sregs; ++i) {
549                                         MONO_INST_NEW (cfg, args [i], OP_ARG);
550                                         args [i]->dreg = sregs [i];
551                                 }
552                         }
553
554                         call = mono_emit_jit_icall_by_info (cfg, info, args);
555                         call->dreg = ins->dreg;
556
557                         NULLIFY_INS (ins);
558                 }
559         }
560
561         if (ins->opcode == OP_NOP) {
562                 if (repl) {
563                         repl->type = type;
564                         return repl;
565                 } else {
566                         /* Use the last emitted instruction */
567                         ins = cfg->cbb->last_ins;
568                         g_assert (ins);
569                         ins->type = type;
570                         g_assert (ins->dreg == dreg);
571                         return ins;
572                 }
573         } else {
574                 return ins;
575         }
576 }
577
578 #if SIZEOF_REGISTER == 4
579 static int lbr_decomp [][2] = {
580         {0, 0}, /* BEQ */
581         {OP_IBGT, OP_IBGE_UN}, /* BGE */
582         {OP_IBGT, OP_IBGT_UN}, /* BGT */
583         {OP_IBLT, OP_IBLE_UN}, /* BLE */
584         {OP_IBLT, OP_IBLT_UN}, /* BLT */
585         {0, 0}, /* BNE_UN */
586         {OP_IBGT_UN, OP_IBGE_UN}, /* BGE_UN */
587         {OP_IBGT_UN, OP_IBGT_UN}, /* BGT_UN */
588         {OP_IBLT_UN, OP_IBLE_UN}, /* BLE_UN */
589         {OP_IBLT_UN, OP_IBLT_UN}, /* BLT_UN */
590 };
591
592 static int lcset_decomp [][2] = {
593         {0, 0}, /* CEQ */
594         {OP_IBLT, OP_IBLE_UN}, /* CGT */
595         {OP_IBLT_UN, OP_IBLE_UN}, /* CGT_UN */
596         {OP_IBGT, OP_IBGE_UN}, /* CLT */
597         {OP_IBGT_UN, OP_IBGE_UN}, /* CLT_UN */
598 };
599 #endif
600
601 /**
602  * mono_decompose_long_opts:
603  *
604  *  Decompose 64bit opcodes into 32bit opcodes on 32 bit platforms.
605  */
606 void
607 mono_decompose_long_opts (MonoCompile *cfg)
608 {
609 #if SIZEOF_REGISTER == 4
610         MonoBasicBlock *bb, *first_bb;
611
612         /*
613          * Some opcodes, like lcall can't be decomposed so the rest of the JIT
614          * needs to be able to handle long vregs.
615          */
616
617         /**
618          * Create a dummy bblock and emit code into it so we can use the normal 
619          * code generation macros.
620          */
621         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
622         first_bb = cfg->cbb;
623
624         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
625                 MonoInst *tree = mono_bb_first_inst(bb, FILTER_IL_SEQ_POINT);
626                 MonoInst *prev = NULL;
627
628                    /*
629                 mono_print_bb (bb, "BEFORE LOWER_LONG_OPTS");
630                 */
631
632                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
633
634                 while (tree) {
635                         mono_arch_decompose_long_opts (cfg, tree);
636
637                         switch (tree->opcode) {
638                         case OP_I8CONST:
639                                 MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_LS (tree->dreg), tree->inst_ls_word);
640                                 MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), tree->inst_ms_word);
641                                 break;
642                         case OP_DUMMY_I8CONST:
643                                 MONO_EMIT_NEW_DUMMY_INIT (cfg, MONO_LVREG_LS (tree->dreg), OP_DUMMY_ICONST);
644                                 MONO_EMIT_NEW_DUMMY_INIT (cfg, MONO_LVREG_MS (tree->dreg), OP_DUMMY_ICONST);
645                                 break;
646                         case OP_LMOVE:
647                         case OP_LCONV_TO_U8:
648                         case OP_LCONV_TO_I8:
649                         case OP_LCONV_TO_OVF_U8_UN:
650                         case OP_LCONV_TO_OVF_I8:
651                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1));
652                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1));
653                                 break;
654                         case OP_STOREI8_MEMBASE_REG:
655                                 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));
656                                 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));
657                                 break;
658                         case OP_LOADI8_MEMBASE:
659                                 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);
660                                 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);
661                                 break;
662
663                         case OP_ICONV_TO_I8: {
664                                 guint32 tmpreg = alloc_ireg (cfg);
665
666                                 /* branchless code:
667                                  * low = reg;
668                                  * tmp = low > -1 ? 1: 0;
669                                  * high = tmp - 1; if low is zero or pos high becomes 0, else -1
670                                  */
671                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1);
672                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, MONO_LVREG_LS (tree->dreg), -1);
673                                 MONO_EMIT_NEW_BIALU (cfg, OP_ICGT, tmpreg, -1, -1);
674                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISUB_IMM, MONO_LVREG_MS (tree->dreg), tmpreg, 1);
675                                 break;
676                         }
677                         case OP_ICONV_TO_U8:
678                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1);
679                                 MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0);
680                                 break;
681                         case OP_ICONV_TO_OVF_I8:
682                                 /* a signed 32 bit num always fits in a signed 64 bit one */
683                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, MONO_LVREG_MS (tree->dreg), tree->sreg1, 31);
684                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1);
685                                 break;
686                         case OP_ICONV_TO_OVF_U8:
687                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1, 0);
688                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
689                                 MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0);
690                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1);
691                                 break;
692                         case OP_ICONV_TO_OVF_I8_UN:
693                         case OP_ICONV_TO_OVF_U8_UN:
694                                 /* an unsigned 32 bit num always fits in an (un)signed 64 bit one */
695                                 MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0);
696                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1);
697                                 break;
698                         case OP_LCONV_TO_I1:
699                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, MONO_LVREG_LS (tree->sreg1));
700                                 break;
701                         case OP_LCONV_TO_U1:
702                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U1, tree->dreg, MONO_LVREG_LS (tree->sreg1));
703                                 break;
704                         case OP_LCONV_TO_I2:
705                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, MONO_LVREG_LS (tree->sreg1));
706                                 break;
707                         case OP_LCONV_TO_U2:
708                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U2, tree->dreg, MONO_LVREG_LS (tree->sreg1));
709                                 break;
710                         case OP_LCONV_TO_I4:
711                         case OP_LCONV_TO_U4:
712                         case OP_LCONV_TO_I:
713                         case OP_LCONV_TO_U:
714                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, MONO_LVREG_LS (tree->sreg1));
715                                 break;
716 #ifndef MONO_ARCH_EMULATE_LCONV_TO_R8
717                         case OP_LCONV_TO_R8:
718                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R8_2, tree->dreg, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_MS (tree->sreg1));
719                                 break;
720 #endif
721 #ifndef MONO_ARCH_EMULATE_LCONV_TO_R4
722                         case OP_LCONV_TO_R4:
723                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R4_2, tree->dreg, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_MS (tree->sreg1));
724                                 break;
725 #endif
726 #ifndef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
727                         case OP_LCONV_TO_R_UN:
728                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R_UN_2, tree->dreg, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_MS (tree->sreg1));
729                                 break;
730 #endif
731                         case OP_LCONV_TO_OVF_I1: {
732                                 MonoBasicBlock *is_negative, *end_label;
733
734                                 NEW_BBLOCK (cfg, is_negative);
735                                 NEW_BBLOCK (cfg, end_label);
736
737                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
738                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
739                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), -1);
740                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
741
742                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
743                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative);
744
745                                 /* Positive */
746                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 127);
747                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
748                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label);
749
750                                 /* Negative */
751                                 MONO_START_BB (cfg, is_negative);
752                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), -128);
753                                 MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException");
754
755                                 MONO_START_BB (cfg, end_label);
756
757                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, MONO_LVREG_LS (tree->sreg1));
758                                 break;
759                         }
760                         case OP_LCONV_TO_OVF_I1_UN:
761                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
762                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
763
764                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 127);
765                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
766                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), -128);
767                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
768                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, MONO_LVREG_LS (tree->sreg1));
769                                 break;
770                         case OP_LCONV_TO_OVF_U1:
771                         case OP_LCONV_TO_OVF_U1_UN:
772                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
773                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
774
775                                 /* probe value to be within 0 to 255 */
776                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 255);
777                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
778                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, MONO_LVREG_LS (tree->sreg1), 0xff);
779                                 break;
780                         case OP_LCONV_TO_OVF_I2: {
781                                 MonoBasicBlock *is_negative, *end_label;
782
783                                 NEW_BBLOCK (cfg, is_negative);
784                                 NEW_BBLOCK (cfg, end_label);
785
786                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
787                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
788                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), -1);
789                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
790
791                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
792                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative);
793
794                                 /* Positive */
795                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 32767);
796                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
797                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label);
798
799                                 /* Negative */
800                                 MONO_START_BB (cfg, is_negative);
801                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), -32768);
802                                 MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException");
803                                 MONO_START_BB (cfg, end_label);
804
805                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, MONO_LVREG_LS (tree->sreg1));
806                                 break;
807                         }
808                         case OP_LCONV_TO_OVF_I2_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
812                                 /* Probe value to be within -32768 and 32767 */
813                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 32767);
814                                 MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException");
815                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), -32768);
816                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
817                                 MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, MONO_LVREG_LS (tree->sreg1));
818                                 break;
819                         case OP_LCONV_TO_OVF_U2:
820                         case OP_LCONV_TO_OVF_U2_UN:
821                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
822                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
823
824                                 /* Probe value to be within 0 and 65535 */
825                                 MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 0xffff);
826                                 MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException");
827                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, MONO_LVREG_LS (tree->sreg1), 0xffff);
828                                 break;
829                         case OP_LCONV_TO_OVF_I4:
830                         case OP_LCONV_TO_OVF_I:
831                                 MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_OVF_I4_2, tree->dreg, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_MS (tree->sreg1));
832                                 break;
833                         case OP_LCONV_TO_OVF_U4:
834                         case OP_LCONV_TO_OVF_U:
835                         case OP_LCONV_TO_OVF_U4_UN:
836                         case OP_LCONV_TO_OVF_U_UN:
837                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
838                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
839                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, MONO_LVREG_LS (tree->sreg1));
840                                 break;
841                         case OP_LCONV_TO_OVF_I_UN:
842                         case OP_LCONV_TO_OVF_I4_UN:
843                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
844                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException");
845                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_LS (tree->sreg1), 0);
846                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
847                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, MONO_LVREG_LS (tree->sreg1));
848                                 break;
849                         case OP_LCONV_TO_OVF_U8:
850                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
851                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
852
853                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1));
854                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1));
855                                 break;
856                         case OP_LCONV_TO_OVF_I8_UN:
857                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0);
858                                 MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException");
859
860                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1));
861                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1));
862                                 break;
863
864                         case OP_LADD:
865                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
866                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
867                                 break;
868                         case OP_LSUB:
869                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
870                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
871                                 break;
872
873                         case OP_LADD_OVF:
874                                 /* ADC sets the condition code */
875                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
876                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
877                                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
878                                 break;
879                         case OP_LADD_OVF_UN:
880                                 /* ADC sets the condition code */
881                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
882                                 MONO_EMIT_NEW_BIALU (cfg, OP_IADC, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
883                                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
884                                 break;
885                         case OP_LSUB_OVF:
886                                 /* SBB sets the condition code */
887                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
888                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
889                                 MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
890                                 break;
891                         case OP_LSUB_OVF_UN:
892                                 /* SBB sets the condition code */
893                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
894                                 MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
895                                 MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
896                                 break;
897                         case OP_LAND:
898                                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
899                                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
900                                 break;
901                         case OP_LOR:
902                                 MONO_EMIT_NEW_BIALU (cfg, OP_IOR, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
903                                 MONO_EMIT_NEW_BIALU (cfg, OP_IOR, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
904                                 break;
905                         case OP_LXOR:
906                                 MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
907                                 MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
908                                 break;
909                         case OP_LNOT:
910                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1));
911                                 MONO_EMIT_NEW_UNALU (cfg, OP_INOT, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1));
912                                 break;
913                         case OP_LNEG:
914                                 /* Handled in mono_arch_decompose_long_opts () */
915                                 g_assert_not_reached ();
916                                 break;
917                         case OP_LMUL:
918                                 /* Emulated */
919                                 /* FIXME: Add OP_BIGMUL optimization */
920                                 break;
921
922                         case OP_LADD_IMM:
923                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADDCC_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word);
924                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word);
925                                 break;
926                         case OP_LSUB_IMM:
927                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUBCC_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word);
928                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SBB_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word);
929                                 break;
930                         case OP_LAND_IMM:
931                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word);
932                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word);
933                                 break;
934                         case OP_LOR_IMM:
935                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word);
936                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word);
937                                 break;
938                         case OP_LXOR_IMM:
939                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word);
940                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word);
941                                 break;
942                         case OP_LSHR_UN_IMM:
943                                 if (tree->inst_c1 == 32) {
944
945                                         /* The original code had this comment: */
946                                         /* special case that gives a nice speedup and happens to workaorund a ppc jit but (for the release)
947                                          * later apply the speedup to the left shift as well
948                                          * See BUG# 57957.
949                                          */
950                                         /* FIXME: Move this to the strength reduction pass */
951                                         /* just move the upper half to the lower and zero the high word */
952                                         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), MONO_LVREG_MS (tree->sreg1));
953                                         MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0);
954                                 }
955                                 break;
956                         case OP_LSHL_IMM:
957                                 if (tree->inst_c1 == 32) {
958                                         /* just move the lower half to the upper and zero the lower word */
959                                         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (tree->dreg), MONO_LVREG_LS (tree->sreg1));
960                                         MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_LS (tree->dreg), 0);
961                                 }
962                                 break;
963
964                         case OP_LCOMPARE: {
965                                 MonoInst *next = mono_inst_next (tree, FILTER_IL_SEQ_POINT);
966
967                                 g_assert (next);
968
969                                 switch (next->opcode) {
970                                 case OP_LBEQ:
971                                 case OP_LBNE_UN: {
972                                         int d1, d2;
973
974                                         /* Branchless version based on gcc code */
975                                         d1 = alloc_ireg (cfg);
976                                         d2 = alloc_ireg (cfg);
977                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
978                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
979                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
980                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
981                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
982                                         NULLIFY_INS (next);
983                                         break;
984                                 }
985                                 case OP_LBGE:
986                                 case OP_LBGT:
987                                 case OP_LBLE:
988                                 case OP_LBLT:
989                                 case OP_LBGE_UN:
990                                 case OP_LBGT_UN:
991                                 case OP_LBLE_UN:
992                                 case OP_LBLT_UN:
993                                         /* Convert into three comparisons + branches */
994                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
995                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lbr_decomp [next->opcode - OP_LBEQ][0], next->inst_true_bb);
996                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
997                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
998                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
999                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
1000                                         NULLIFY_INS (next);
1001                                         break;
1002                                 case OP_LCEQ: {
1003                                         int d1, d2;
1004         
1005                                         /* Branchless version based on gcc code */
1006                                         d1 = alloc_ireg (cfg);
1007                                         d2 = alloc_ireg (cfg);
1008                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
1009                                         MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
1010                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
1011
1012                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
1013                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
1014                                         NULLIFY_INS (next);
1015                                         break;
1016                                 }
1017                                 case OP_LCLT:
1018                                 case OP_LCLT_UN:
1019                                 case OP_LCGT:
1020                                 case OP_LCGT_UN: {
1021                                         MonoBasicBlock *set_to_0, *set_to_1;
1022         
1023                                         NEW_BBLOCK (cfg, set_to_0);
1024                                         NEW_BBLOCK (cfg, set_to_1);
1025
1026                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 0);
1027                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
1028                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][0], set_to_0);
1029                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2));
1030                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, set_to_1);
1031                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2));
1032                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][1], set_to_0);
1033                                         MONO_START_BB (cfg, set_to_1);
1034                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
1035                                         MONO_START_BB (cfg, set_to_0);
1036                                         NULLIFY_INS (next);
1037                                         break;  
1038                                 }
1039                                 default:
1040                                         g_assert_not_reached ();
1041                                 }
1042                                 break;
1043                         }
1044
1045                         /* Not yet used, since lcompare is decomposed before local cprop */
1046                         case OP_LCOMPARE_IMM: {
1047                                 MonoInst *next = mono_inst_next (tree, FILTER_IL_SEQ_POINT);
1048                                 guint32 low_imm = tree->inst_ls_word;
1049                                 guint32 high_imm = tree->inst_ms_word;
1050                                 int low_reg = MONO_LVREG_LS (tree->sreg1);
1051                                 int high_reg = MONO_LVREG_MS (tree->sreg1);
1052
1053                                 g_assert (next);
1054
1055                                 switch (next->opcode) {
1056                                 case OP_LBEQ:
1057                                 case OP_LBNE_UN: {
1058                                         int d1, d2;
1059
1060                                         /* Branchless version based on gcc code */
1061                                         d1 = alloc_ireg (cfg);
1062                                         d2 = alloc_ireg (cfg);
1063                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d1, low_reg, low_imm);
1064                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d2, high_reg, high_imm);
1065                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
1066                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
1067                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
1068                                         NULLIFY_INS (next);
1069                                         break;
1070                                 }
1071
1072                                 case OP_LBGE:
1073                                 case OP_LBGT:
1074                                 case OP_LBLE:
1075                                 case OP_LBLT:
1076                                 case OP_LBGE_UN:
1077                                 case OP_LBGT_UN:
1078                                 case OP_LBLE_UN:
1079                                 case OP_LBLT_UN:
1080                                         /* Convert into three comparisons + branches */
1081                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1082                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lbr_decomp [next->opcode - OP_LBEQ][0], next->inst_true_bb);
1083                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1084                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
1085                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
1086                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
1087                                         NULLIFY_INS (next);
1088                                         break;
1089                                 case OP_LCEQ: {
1090                                         int d1, d2;
1091         
1092                                         /* Branchless version based on gcc code */
1093                                         d1 = alloc_ireg (cfg);
1094                                         d2 = alloc_ireg (cfg);
1095                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d1, low_reg, low_imm);
1096                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IXOR_IMM, d2, high_reg, high_imm);
1097                                         MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
1098
1099                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
1100                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
1101                                         NULLIFY_INS (next);
1102                                         break;
1103                                 }
1104                                 case OP_LCLT:
1105                                 case OP_LCLT_UN:
1106                                 case OP_LCGT:
1107                                 case OP_LCGT_UN: {
1108                                         MonoBasicBlock *set_to_0, *set_to_1;
1109         
1110                                         NEW_BBLOCK (cfg, set_to_0);
1111                                         NEW_BBLOCK (cfg, set_to_1);
1112
1113                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 0);
1114                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1115                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][0], set_to_0);
1116                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, high_reg, high_imm);
1117                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, set_to_1);
1118                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
1119                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][1], set_to_0);
1120                                         MONO_START_BB (cfg, set_to_1);
1121                                         MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
1122                                         MONO_START_BB (cfg, set_to_0);
1123                                         NULLIFY_INS (next);
1124                                         break;  
1125                                 }
1126                                 default:
1127                                         g_assert_not_reached ();
1128                                 }
1129                                 break;
1130                         }
1131
1132                         default:
1133                                 break;
1134                         }
1135
1136                         if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1137                                 MonoInst *new_prev;
1138
1139                                 /* Replace the original instruction with the new code sequence */
1140
1141                                 /* Ignore the new value of prev */
1142                                 new_prev = prev;
1143                                 mono_replace_ins (cfg, bb, tree, &new_prev, first_bb, cfg->cbb);
1144
1145                                 /* Process the newly added ops again since they can be long ops too */
1146                                 if (prev)
1147                                         tree = mono_inst_next (prev, FILTER_IL_SEQ_POINT);
1148                                 else
1149                                         tree = mono_bb_first_inst (bb, FILTER_IL_SEQ_POINT);
1150
1151                                 first_bb->code = first_bb->last_ins = NULL;
1152                                 first_bb->in_count = first_bb->out_count = 0;
1153                                 cfg->cbb = first_bb;
1154                         }
1155                         else {
1156                                 prev = tree;
1157                                 tree = mono_inst_next (tree, FILTER_IL_SEQ_POINT);
1158                         }
1159                 }
1160         }
1161 #endif
1162
1163         /*
1164         for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
1165                 mono_print_bb (bb, "AFTER LOWER-LONG-OPTS");
1166         */
1167 }
1168
1169 /**
1170  * mono_decompose_vtype_opts:
1171  *
1172  *  Decompose valuetype opcodes.
1173  */
1174 void
1175 mono_decompose_vtype_opts (MonoCompile *cfg)
1176 {
1177         MonoBasicBlock *bb, *first_bb;
1178
1179         /**
1180          * Using OP_V opcodes and decomposing them later have two main benefits:
1181          * - it simplifies method_to_ir () since there is no need to special-case vtypes
1182          *   everywhere.
1183          * - it gets rid of the LDADDR opcodes generated when vtype operations are decomposed,
1184          *   enabling optimizations to work on vtypes too.
1185          * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it 
1186          * can be executed anytime. It should be executed as late as possible so vtype
1187          * opcodes can be optimized by the other passes.
1188          * The pinvoke wrappers need to manipulate vtypes in their unmanaged representation.
1189          * This is indicated by setting the 'backend.is_pinvoke' field of the MonoInst for the 
1190          * var to 1.
1191          * This is done on demand, ie. by the LDNATIVEOBJ opcode, and propagated by this pass 
1192          * when OP_VMOVE opcodes are decomposed.
1193          */
1194
1195         /* 
1196          * Vregs have no associated type information, so we store the type of the vregs
1197          * in ins->klass.
1198          */
1199
1200         /**
1201          * Create a dummy bblock and emit code into it so we can use the normal 
1202          * code generation macros.
1203          */
1204         cfg->cbb = (MonoBasicBlock *)mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1205         first_bb = cfg->cbb;
1206
1207         /* For LLVM, decompose only the OP_STOREV_MEMBASE opcodes, which need write barriers and the gsharedvt opcodes */
1208
1209         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1210                 MonoInst *ins;
1211                 MonoInst *prev = NULL;
1212                 MonoInst *src_var, *dest_var, *src, *dest;
1213                 gboolean restart;
1214                 int dreg;
1215
1216                 if (cfg->verbose_level > 2) mono_print_bb (bb, "BEFORE LOWER-VTYPE-OPTS ");
1217
1218                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1219                 restart = TRUE;
1220
1221                 while (restart) {
1222                         restart = FALSE;
1223
1224                         for (ins = bb->code; ins; ins = ins->next) {
1225                                 switch (ins->opcode) {
1226                                 case OP_VMOVE: {
1227                                         g_assert (ins->klass);
1228                                         if (COMPILE_LLVM (cfg) && !mini_is_gsharedvt_klass (ins->klass))
1229                                                 break;
1230                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1231                                         dest_var = get_vreg_to_inst (cfg, ins->dreg);
1232
1233                                         if (!src_var)
1234                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1235
1236                                         if (!dest_var)
1237                                                 dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1238
1239                                         // FIXME:
1240                                         if (src_var->backend.is_pinvoke)
1241                                                 dest_var->backend.is_pinvoke = 1;
1242
1243                                         EMIT_NEW_VARLOADA ((cfg), (src), src_var, src_var->inst_vtype);
1244                                         EMIT_NEW_VARLOADA ((cfg), (dest), dest_var, dest_var->inst_vtype);
1245
1246                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1247                                         break;
1248                                 }
1249                                 case OP_VZERO:
1250                                         if (COMPILE_LLVM (cfg) && !mini_is_gsharedvt_klass (ins->klass))
1251                                                 break;
1252
1253                                         g_assert (ins->klass);
1254
1255                                         EMIT_NEW_VARLOADA_VREG (cfg, dest, ins->dreg, &ins->klass->byval_arg);
1256                                         mini_emit_initobj (cfg, dest, NULL, ins->klass);
1257                                         
1258                                         if (cfg->compute_gc_maps) {
1259                                                 MonoInst *tmp;
1260
1261                                                 /* 
1262                                                  * Tell the GC map code that the vtype is considered live after
1263                                                  * the initialization.
1264                                                  */
1265                                                 MONO_INST_NEW (cfg, tmp, OP_GC_LIVENESS_DEF);
1266                                                 tmp->inst_c1 = ins->dreg;
1267                                                 MONO_ADD_INS (cfg->cbb, tmp);
1268                                         }
1269                                         break;
1270                                 case OP_DUMMY_VZERO:
1271                                         if (COMPILE_LLVM (cfg))
1272                                                 break;
1273
1274                                         NULLIFY_INS (ins);
1275                                         break;
1276                                 case OP_STOREV_MEMBASE: {
1277                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1278
1279                                         if (!src_var) {
1280                                                 g_assert (ins->klass);
1281                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1282                                         }
1283
1284                                         EMIT_NEW_VARLOADA_VREG ((cfg), (src), ins->sreg1, &ins->klass->byval_arg);
1285
1286                                         dreg = alloc_preg (cfg);
1287                                         EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
1288                                         mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
1289                                         break;
1290                                 }
1291                                 case OP_LOADV_MEMBASE: {
1292                                         g_assert (ins->klass);
1293                                         if (COMPILE_LLVM (cfg) && !mini_is_gsharedvt_klass (ins->klass))
1294                                                 break;
1295
1296                                         dest_var = get_vreg_to_inst (cfg, ins->dreg);
1297                                         // FIXME-VT:
1298                                         // FIXME:
1299                                         if (!dest_var)
1300                                                 dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
1301
1302                                         dreg = alloc_preg (cfg);
1303                                         EMIT_NEW_BIALU_IMM (cfg, src, OP_ADD_IMM, dreg, ins->inst_basereg, ins->inst_offset);
1304                                         EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
1305                                         mini_emit_stobj (cfg, dest, src, dest_var->klass, dest_var->backend.is_pinvoke);
1306                                         break;
1307                                 }
1308                                 case OP_OUTARG_VT: {
1309                                         if (COMPILE_LLVM (cfg))
1310                                                 break;
1311
1312                                         g_assert (ins->klass);
1313
1314                                         src_var = get_vreg_to_inst (cfg, ins->sreg1);
1315                                         if (!src_var)
1316                                                 src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
1317                                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
1318
1319                                         mono_arch_emit_outarg_vt (cfg, ins, src);
1320
1321                                         /* This might be decomposed into other vtype opcodes */
1322                                         restart = TRUE;
1323                                         break;
1324                                 }
1325                                 case OP_OUTARG_VTRETADDR: {
1326                                         MonoCallInst *call = (MonoCallInst*)ins->inst_p1;
1327
1328                                         src_var = get_vreg_to_inst (cfg, call->inst.dreg);
1329                                         if (!src_var)
1330                                                 src_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
1331                                         // FIXME: src_var->backend.is_pinvoke ?
1332
1333                                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
1334                                         src->dreg = ins->dreg;
1335                                         break;
1336                                 }
1337                                 case OP_VCALL:
1338                                 case OP_VCALL_REG:
1339                                 case OP_VCALL_MEMBASE: {
1340                                         MonoCallInst *call = (MonoCallInst*)ins;
1341                                         int size;
1342
1343                                         if (COMPILE_LLVM (cfg))
1344                                                 break;
1345
1346                                         if (call->vret_in_reg) {
1347                                                 MonoCallInst *call2;
1348
1349                                                 /* Replace the vcall with a scalar call */
1350                                                 MONO_INST_NEW_CALL (cfg, call2, OP_NOP);
1351                                                 memcpy (call2, call, sizeof (MonoCallInst));
1352                                                 switch (ins->opcode) {
1353                                                 case OP_VCALL:
1354                                                         call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL : OP_CALL;
1355                                                         break;
1356                                                 case OP_VCALL_REG:
1357                                                         call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_REG : OP_CALL_REG;
1358                                                         break;
1359                                                 case OP_VCALL_MEMBASE:
1360                                                         call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_MEMBASE : OP_CALL_MEMBASE;
1361                                                         break;
1362                                                 }
1363                                                 call2->inst.dreg = alloc_preg (cfg);
1364                                                 MONO_ADD_INS (cfg->cbb, ((MonoInst*)call2));
1365
1366                                                 /* Compute the vtype location */
1367                                                 dest_var = get_vreg_to_inst (cfg, call->inst.dreg);
1368                                                 if (!dest_var)
1369                                                         dest_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
1370                                                 EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
1371
1372                                                 /* Save the result */
1373                                                 if (dest_var->backend.is_pinvoke)
1374                                                         size = mono_class_native_size (mono_class_from_mono_type (dest_var->inst_vtype), NULL);
1375                                                 else
1376                                                         size = mono_type_size (dest_var->inst_vtype, NULL);
1377                                                 switch (size) {
1378                                                 case 1:
1379                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1380                                                         break;
1381                                                 case 2:
1382                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1383                                                         break;
1384                                                 case 3:
1385                                                 case 4:
1386                                                         if (call->vret_in_reg_fp)
1387                                                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1388                                                         else
1389                                                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1390                                                         break;
1391                                                 case 5:
1392                                                 case 6:
1393                                                 case 7:
1394                                                 case 8:
1395                                                         if (call->vret_in_reg_fp) {
1396                                                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1397                                                                 break;
1398                                                         }
1399 #if SIZEOF_REGISTER == 4
1400                                                         /*
1401                                                         FIXME Other ABIs might return in different regs than the ones used for LCALL.
1402                                                         FIXME It would be even nicer to be able to leverage the long decompose stuff.
1403                                                         */
1404                                                         switch (call2->inst.opcode) {
1405                                                         case OP_CALL:
1406                                                                 call2->inst.opcode = OP_LCALL;
1407                                                                 break;
1408                                                         case OP_CALL_REG:
1409                                                                 call2->inst.opcode = OP_LCALL_REG;
1410                                                                 break;
1411                                                         case OP_CALL_MEMBASE:
1412                                                                 call2->inst.opcode = OP_LCALL_MEMBASE;
1413                                                                 break;
1414                                                         }
1415                                                         call2->inst.dreg = alloc_lreg (cfg);
1416                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_MS_WORD_OFFSET, MONO_LVREG_MS (call2->inst.dreg));
1417                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_LS_WORD_OFFSET, MONO_LVREG_LS (call2->inst.dreg));
1418 #else
1419                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1420 #endif
1421                                                         break;
1422                                                 default:
1423                                                         /* This assumes the vtype is sizeof (gpointer) long */
1424                                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
1425                                                         break;
1426                                                 }
1427                                         } else {
1428                                                 switch (ins->opcode) {
1429                                                 case OP_VCALL:
1430                                                         ins->opcode = OP_VCALL2;
1431                                                         break;
1432                                                 case OP_VCALL_REG:
1433                                                         ins->opcode = OP_VCALL2_REG;
1434                                                         break;
1435                                                 case OP_VCALL_MEMBASE:
1436                                                         ins->opcode = OP_VCALL2_MEMBASE;
1437                                                         break;
1438                                                 }
1439                                                 ins->dreg = -1;
1440                                         }
1441                                         break;
1442                                 }
1443                                 default:
1444                                         break;
1445                                 }
1446
1447                                 g_assert (cfg->cbb == first_bb);
1448
1449                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1450                                         /* Replace the original instruction with the new code sequence */
1451
1452                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1453                                         first_bb->code = first_bb->last_ins = NULL;
1454                                         first_bb->in_count = first_bb->out_count = 0;
1455                                         cfg->cbb = first_bb;
1456                                 }
1457                                 else
1458                                         prev = ins;
1459                         }
1460                 }
1461
1462                 if (cfg->verbose_level > 2) mono_print_bb (bb, "AFTER LOWER-VTYPE-OPTS ");
1463         }
1464 }
1465
1466 inline static MonoInst *
1467 mono_get_domainvar (MonoCompile *cfg)
1468 {
1469         if (!cfg->domainvar)
1470                 cfg->domainvar = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
1471         return cfg->domainvar;
1472 }
1473
1474 /**
1475  * mono_decompose_array_access_opts:
1476  *
1477  *  Decompose array access opcodes.
1478  */
1479 void
1480 mono_decompose_array_access_opts (MonoCompile *cfg)
1481 {
1482         MonoBasicBlock *bb, *first_bb;
1483
1484         /*
1485          * Unlike decompose_long_opts, this pass does not alter the CFG of the method so it 
1486          * can be executed anytime. It should be run before decompose_long
1487          */
1488
1489         /**
1490          * Create a dummy bblock and emit code into it so we can use the normal 
1491          * code generation macros.
1492          */
1493         cfg->cbb = (MonoBasicBlock *)mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1494         first_bb = cfg->cbb;
1495
1496         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1497                 MonoInst *ins;
1498                 MonoInst *prev = NULL;
1499                 MonoInst *dest;
1500                 MonoInst *iargs [3];
1501                 gboolean restart;
1502
1503                 if (!bb->has_array_access)
1504                         continue;
1505
1506                 if (cfg->verbose_level > 3) mono_print_bb (bb, "BEFORE DECOMPOSE-ARRAY-ACCESS-OPTS ");
1507
1508                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1509                 restart = TRUE;
1510
1511                 while (restart) {
1512                         restart = FALSE;
1513
1514                         for (ins = bb->code; ins; ins = ins->next) {
1515                                 switch (ins->opcode) {
1516                                 case OP_LDLEN:
1517                                         NEW_LOAD_MEMBASE_FLAGS (cfg, dest, OP_LOADI4_MEMBASE, ins->dreg, ins->sreg1,
1518                                                                                         MONO_STRUCT_OFFSET (MonoArray, max_length), ins->flags | MONO_INST_INVARIANT_LOAD);
1519                                         MONO_ADD_INS (cfg->cbb, dest);
1520                                         break;
1521                                 case OP_BOUNDS_CHECK:
1522                                         MONO_EMIT_NULL_CHECK (cfg, ins->sreg1);
1523                                         if (COMPILE_LLVM (cfg))
1524                                                 MONO_EMIT_DEFAULT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2, ins->flags & MONO_INST_FAULT);
1525                                         else
1526                                                 MONO_ARCH_EMIT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2);
1527                                         break;
1528                                 case OP_NEWARR:
1529                                         if (cfg->opt & MONO_OPT_SHARED) {
1530                                                 EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
1531                                                 EMIT_NEW_CLASSCONST (cfg, iargs [1], ins->inst_newa_class);
1532                                                 MONO_INST_NEW (cfg, iargs [2], OP_MOVE);
1533                                                 iargs [2]->dreg = ins->sreg1;
1534
1535                                                 dest = mono_emit_jit_icall (cfg, mono_array_new, iargs);
1536                                                 dest->dreg = ins->dreg;
1537                                         } else {
1538                                                 MonoClass *array_class = mono_array_class_get (ins->inst_newa_class, 1);
1539                                                 MonoVTable *vtable = mono_class_vtable (cfg->domain, array_class);
1540                                                 MonoMethod *managed_alloc = mono_gc_get_managed_array_allocator (array_class);
1541
1542                                                 g_assert (vtable); /*This shall not fail since we check for this condition on OP_NEWARR creation*/
1543                                                 NEW_VTABLECONST (cfg, iargs [0], vtable);
1544                                                 MONO_ADD_INS (cfg->cbb, iargs [0]);
1545                                                 MONO_INST_NEW (cfg, iargs [1], OP_MOVE);
1546                                                 iargs [1]->dreg = ins->sreg1;
1547
1548                                                 if (managed_alloc)
1549                                                         dest = mono_emit_method_call (cfg, managed_alloc, iargs, NULL);
1550                                                 else
1551                                                         dest = mono_emit_jit_icall (cfg, mono_array_new_specific, iargs);
1552                                                 dest->dreg = ins->dreg;
1553                                         }
1554                                         break;
1555                                 case OP_STRLEN:
1556                                         MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS (cfg, OP_LOADI4_MEMBASE, ins->dreg,
1557                                                                                                                  ins->sreg1, MONO_STRUCT_OFFSET (MonoString, length), ins->flags | MONO_INST_INVARIANT_LOAD);
1558                                         break;
1559                                 default:
1560                                         break;
1561                                 }
1562
1563                                 g_assert (cfg->cbb == first_bb);
1564
1565                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1566                                         /* Replace the original instruction with the new code sequence */
1567
1568                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1569                                         first_bb->code = first_bb->last_ins = NULL;
1570                                         first_bb->in_count = first_bb->out_count = 0;
1571                                         cfg->cbb = first_bb;
1572                                 }
1573                                 else
1574                                         prev = ins;
1575                         }
1576                 }
1577
1578                 if (cfg->verbose_level > 3) mono_print_bb (bb, "AFTER DECOMPOSE-ARRAY-ACCESS-OPTS ");
1579         }
1580 }
1581
1582 typedef union {
1583         guint32 vali [2];
1584         gint64 vall;
1585         double vald;
1586 } DVal;
1587
1588 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
1589
1590 /**
1591  * mono_decompose_soft_float:
1592  *
1593  *  Soft float support on ARM. We store each double value in a pair of integer vregs,
1594  * similar to long support on 32 bit platforms. 32 bit float values require special
1595  * handling when used as locals, arguments, and in calls.
1596  * One big problem with soft-float is that there are few r4 test cases in our test suite.
1597  */
1598 void
1599 mono_decompose_soft_float (MonoCompile *cfg)
1600 {
1601         MonoBasicBlock *bb, *first_bb;
1602
1603         /*
1604          * This pass creates long opcodes, so it should be run before decompose_long_opts ().
1605          */
1606
1607         /**
1608          * Create a dummy bblock and emit code into it so we can use the normal 
1609          * code generation macros.
1610          */
1611         cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
1612         first_bb = cfg->cbb;
1613
1614         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
1615                 MonoInst *ins;
1616                 MonoInst *prev = NULL;
1617                 gboolean restart;
1618
1619                 if (cfg->verbose_level > 3) mono_print_bb (bb, "BEFORE HANDLE-SOFT-FLOAT ");
1620
1621                 cfg->cbb->code = cfg->cbb->last_ins = NULL;
1622                 restart = TRUE;
1623
1624                 while (restart) {
1625                         restart = FALSE;
1626
1627                         for (ins = bb->code; ins; ins = ins->next) {
1628                                 const char *spec = INS_INFO (ins->opcode);
1629
1630                                 /* Most fp operations are handled automatically by opcode emulation */
1631
1632                                 switch (ins->opcode) {
1633                                 case OP_R8CONST: {
1634                                         DVal d;
1635                                         d.vald = *(double*)ins->inst_p0;
1636                                         MONO_EMIT_NEW_I8CONST (cfg, ins->dreg, d.vall);
1637                                         break;
1638                                 }
1639                                 case OP_R4CONST: {
1640                                         DVal d;
1641                                         /* We load the r8 value */
1642                                         d.vald = *(float*)ins->inst_p0;
1643                                         MONO_EMIT_NEW_I8CONST (cfg, ins->dreg, d.vall);
1644                                         break;
1645                                 }
1646                                 case OP_FMOVE:
1647                                         ins->opcode = OP_LMOVE;
1648                                         break;
1649                                 case OP_FGETLOW32:
1650                                         ins->opcode = OP_MOVE;
1651                                         ins->sreg1 = MONO_LVREG_LS (ins->sreg1);
1652                                         break;
1653                                 case OP_FGETHIGH32:
1654                                         ins->opcode = OP_MOVE;
1655                                         ins->sreg1 = MONO_LVREG_MS (ins->sreg1);
1656                                         break;
1657                                 case OP_SETFRET: {
1658                                         int reg = ins->sreg1;
1659
1660                                         ins->opcode = OP_SETLRET;
1661                                         ins->dreg = -1;
1662                                         ins->sreg1 = MONO_LVREG_LS (reg);
1663                                         ins->sreg2 = MONO_LVREG_MS (reg);
1664                                         break;
1665                                 }
1666                                 case OP_LOADR8_MEMBASE:
1667                                         ins->opcode = OP_LOADI8_MEMBASE;
1668                                         break;
1669                                 case OP_STORER8_MEMBASE_REG:
1670                                         ins->opcode = OP_STOREI8_MEMBASE_REG;
1671                                         break;
1672                                 case OP_STORER4_MEMBASE_REG: {
1673                                         MonoInst *iargs [2];
1674                                         int addr_reg;
1675
1676                                         /* Arg 1 is the double value */
1677                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1678                                         iargs [0]->dreg = ins->sreg1;
1679
1680                                         /* Arg 2 is the address to store to */
1681                                         addr_reg = mono_alloc_preg (cfg);
1682                                         EMIT_NEW_BIALU_IMM (cfg, iargs [1], OP_PADD_IMM, addr_reg, ins->inst_destbasereg, ins->inst_offset);
1683                                         mono_emit_jit_icall (cfg, mono_fstore_r4, iargs);
1684                                         restart = TRUE;
1685                                         break;
1686                                 }
1687                                 case OP_LOADR4_MEMBASE: {
1688                                         MonoInst *iargs [1];
1689                                         MonoInst *conv;
1690                                         int addr_reg;
1691
1692                                         addr_reg = mono_alloc_preg (cfg);
1693                                         EMIT_NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, addr_reg, ins->inst_basereg, ins->inst_offset);
1694                                         conv = mono_emit_jit_icall (cfg, mono_fload_r4, iargs);
1695                                         conv->dreg = ins->dreg;
1696                                         break;
1697                                 }                                       
1698                                 case OP_FCALL:
1699                                 case OP_FCALL_REG:
1700                                 case OP_FCALL_MEMBASE: {
1701                                         MonoCallInst *call = (MonoCallInst*)ins;
1702                                         if (call->signature->ret->type == MONO_TYPE_R4) {
1703                                                 MonoCallInst *call2;
1704                                                 MonoInst *iargs [1];
1705                                                 MonoInst *conv;
1706                                                 GSList *l;
1707
1708                                                 /* Convert the call into a call returning an int */
1709                                                 MONO_INST_NEW_CALL (cfg, call2, OP_CALL);
1710                                                 memcpy (call2, call, sizeof (MonoCallInst));
1711                                                 switch (ins->opcode) {
1712                                                 case OP_FCALL:
1713                                                         call2->inst.opcode = OP_CALL;
1714                                                         break;
1715                                                 case OP_FCALL_REG:
1716                                                         call2->inst.opcode = OP_CALL_REG;
1717                                                         break;
1718                                                 case OP_FCALL_MEMBASE:
1719                                                         call2->inst.opcode = OP_CALL_MEMBASE;
1720                                                         break;
1721                                                 default:
1722                                                         g_assert_not_reached ();
1723                                                 }
1724                                                 call2->inst.dreg = mono_alloc_ireg (cfg);
1725                                                 MONO_ADD_INS (cfg->cbb, (MonoInst*)call2);
1726
1727                                                 /* Remap OUTARG_VT instructions referencing this call */
1728                                                 for (l = call->outarg_vts; l; l = l->next)
1729                                                         ((MonoInst*)(l->data))->inst_p0 = call2;
1730
1731                                                 /* FIXME: Optimize this */
1732
1733                                                 /* Emit an r4->r8 conversion */
1734                                                 EMIT_NEW_VARLOADA_VREG (cfg, iargs [0], call2->inst.dreg, &mono_defaults.int32_class->byval_arg);
1735                                                 conv = mono_emit_jit_icall (cfg, mono_fload_r4, iargs);
1736                                                 conv->dreg = ins->dreg;
1737
1738                                                 /* The call sequence might include fp ins */
1739                                                 restart = TRUE;
1740                                         } else {
1741                                                 switch (ins->opcode) {
1742                                                 case OP_FCALL:
1743                                                         ins->opcode = OP_LCALL;
1744                                                         break;
1745                                                 case OP_FCALL_REG:
1746                                                         ins->opcode = OP_LCALL_REG;
1747                                                         break;
1748                                                 case OP_FCALL_MEMBASE:
1749                                                         ins->opcode = OP_LCALL_MEMBASE;
1750                                                         break;
1751                                                 default:
1752                                                         g_assert_not_reached ();
1753                                                 }
1754                                         }
1755                                         break;
1756                                 }
1757                                 case OP_FCOMPARE: {
1758                                         MonoJitICallInfo *info;
1759                                         MonoInst *iargs [2];
1760                                         MonoInst *call, *cmp, *br;
1761
1762                                         /* Convert fcompare+fbcc to icall+icompare+beq */
1763
1764                                         if (!ins->next) {
1765                                                 /* The branch might be optimized away */
1766                                                 NULLIFY_INS (ins);
1767                                                 break;
1768                                         }
1769
1770                                         info = mono_find_jit_opcode_emulation (ins->next->opcode);
1771                                         if (!info) {
1772                                                 /* The branch might be optimized away */
1773                                                 NULLIFY_INS (ins);
1774                                                 break;
1775                                         }
1776
1777                                         /* Create dummy MonoInst's for the arguments */
1778                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1779                                         iargs [0]->dreg = ins->sreg1;
1780                                         MONO_INST_NEW (cfg, iargs [1], OP_ARG);
1781                                         iargs [1]->dreg = ins->sreg2;
1782
1783                                         call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, iargs);
1784
1785                                         MONO_INST_NEW (cfg, cmp, OP_ICOMPARE_IMM);
1786                                         cmp->sreg1 = call->dreg;
1787                                         cmp->inst_imm = 0;
1788                                         MONO_ADD_INS (cfg->cbb, cmp);
1789                                         
1790                                         MONO_INST_NEW (cfg, br, OP_IBNE_UN);
1791                                         br->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof (gpointer) * 2);
1792                                         br->inst_true_bb = ins->next->inst_true_bb;
1793                                         br->inst_false_bb = ins->next->inst_false_bb;
1794                                         MONO_ADD_INS (cfg->cbb, br);
1795
1796                                         /* The call sequence might include fp ins */
1797                                         restart = TRUE;
1798
1799                                         /* Skip fbcc or fccc */
1800                                         NULLIFY_INS (ins->next);
1801                                         break;
1802                                 }
1803                                 case OP_FCEQ:
1804                                 case OP_FCGT:
1805                                 case OP_FCGT_UN:
1806                                 case OP_FCLT:
1807                                 case OP_FCLT_UN: {
1808                                         MonoJitICallInfo *info;
1809                                         MonoInst *iargs [2];
1810                                         MonoInst *call;
1811
1812                                         /* Convert fccc to icall+icompare+iceq */
1813
1814                                         info = mono_find_jit_opcode_emulation (ins->opcode);
1815                                         g_assert (info);
1816
1817                                         /* Create dummy MonoInst's for the arguments */
1818                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1819                                         iargs [0]->dreg = ins->sreg1;
1820                                         MONO_INST_NEW (cfg, iargs [1], OP_ARG);
1821                                         iargs [1]->dreg = ins->sreg2;
1822
1823                                         call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, iargs);
1824
1825                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, call->dreg, 1);
1826                                         MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, ins->dreg, -1);
1827
1828                                         /* The call sequence might include fp ins */
1829                                         restart = TRUE;
1830                                         break;
1831                                 }
1832                                 case OP_CKFINITE: {
1833                                         MonoInst *iargs [2];
1834                                         MonoInst *call, *cmp;
1835
1836                                         /* Convert to icall+icompare+cond_exc+move */
1837
1838                                         /* Create dummy MonoInst's for the arguments */
1839                                         MONO_INST_NEW (cfg, iargs [0], OP_ARG);
1840                                         iargs [0]->dreg = ins->sreg1;
1841
1842                                         call = mono_emit_jit_icall (cfg, mono_isfinite, iargs);
1843
1844                                         MONO_INST_NEW (cfg, cmp, OP_ICOMPARE_IMM);
1845                                         cmp->sreg1 = call->dreg;
1846                                         cmp->inst_imm = 1;
1847                                         MONO_ADD_INS (cfg->cbb, cmp);
1848
1849                                         MONO_EMIT_NEW_COND_EXC (cfg, INE_UN, "ArithmeticException");
1850
1851                                         /* Do the assignment if the value is finite */
1852                                         MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, ins->dreg, ins->sreg1);
1853
1854                                         restart = TRUE;
1855                                         break;
1856                                 }
1857                                 default:
1858                                         if (spec [MONO_INST_SRC1] == 'f' || spec [MONO_INST_SRC2] == 'f' || spec [MONO_INST_DEST] == 'f') {
1859                                                 mono_print_ins (ins);
1860                                                 g_assert_not_reached ();
1861                                         }
1862                                         break;
1863                                 }
1864
1865                                 g_assert (cfg->cbb == first_bb);
1866
1867                                 if (cfg->cbb->code || (cfg->cbb != first_bb)) {
1868                                         /* Replace the original instruction with the new code sequence */
1869
1870                                         mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
1871                                         first_bb->code = first_bb->last_ins = NULL;
1872                                         first_bb->in_count = first_bb->out_count = 0;
1873                                         cfg->cbb = first_bb;
1874                                 }
1875                                 else
1876                                         prev = ins;
1877                         }
1878                 }
1879
1880                 if (cfg->verbose_level > 3) mono_print_bb (bb, "AFTER HANDLE-SOFT-FLOAT ");
1881         }
1882
1883         mono_decompose_long_opts (cfg);
1884 }
1885
1886 #endif
1887
1888 #endif /* DISABLE_JIT */