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