[xbuild] Evaluate Import with MSBuildThisFile* properties set.
[mono.git] / mono / mini / mini-x86.c
1 /*
2  * mini-x86.c: x86 backend for the Mono code generator
3  *
4  * Authors:
5  *   Paolo Molaro (lupus@ximian.com)
6  *   Dietmar Maurer (dietmar@ximian.com)
7  *   Patrik Torstensson
8  *
9  * (C) 2003 Ximian, Inc.
10  */
11 #include "mini.h"
12 #include <string.h>
13 #include <math.h>
14 #ifdef HAVE_UNISTD_H
15 #include <unistd.h>
16 #endif
17
18 #include <mono/metadata/appdomain.h>
19 #include <mono/metadata/debug-helpers.h>
20 #include <mono/metadata/threads.h>
21 #include <mono/metadata/profiler-private.h>
22 #include <mono/metadata/mono-debug.h>
23 #include <mono/metadata/gc-internal.h>
24 #include <mono/utils/mono-math.h>
25 #include <mono/utils/mono-counters.h>
26 #include <mono/utils/mono-mmap.h>
27
28 #include "trace.h"
29 #include "mini-x86.h"
30 #include "cpu-x86.h"
31 #include "ir-emit.h"
32
33 /* On windows, these hold the key returned by TlsAlloc () */
34 static gint lmf_tls_offset = -1;
35 static gint lmf_addr_tls_offset = -1;
36 static gint appdomain_tls_offset = -1;
37
38 #ifdef MONO_XEN_OPT
39 static gboolean optimize_for_xen = TRUE;
40 #else
41 #define optimize_for_xen 0
42 #endif
43
44 #ifdef TARGET_WIN32
45 static gboolean is_win32 = TRUE;
46 #else
47 static gboolean is_win32 = FALSE;
48 #endif
49
50 /* This mutex protects architecture specific caches */
51 #define mono_mini_arch_lock() EnterCriticalSection (&mini_arch_mutex)
52 #define mono_mini_arch_unlock() LeaveCriticalSection (&mini_arch_mutex)
53 static CRITICAL_SECTION mini_arch_mutex;
54
55 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
56
57 #define ARGS_OFFSET 8
58
59 #ifdef TARGET_WIN32
60 /* Under windows, the default pinvoke calling convention is stdcall */
61 #define CALLCONV_IS_STDCALL(sig) ((((sig)->call_convention) == MONO_CALL_STDCALL) || ((sig)->pinvoke && ((sig)->call_convention) == MONO_CALL_DEFAULT))
62 #else
63 #define CALLCONV_IS_STDCALL(sig) (((sig)->call_convention) == MONO_CALL_STDCALL)
64 #endif
65
66 #define X86_IS_CALLEE_SAVED_REG(reg) (((reg) == X86_EBX) || ((reg) == X86_EDI) || ((reg) == X86_ESI))
67
68 MonoBreakpointInfo
69 mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
70
71
72 #ifdef __native_client_codegen__
73 const guint kNaClAlignment = kNaClAlignmentX86;
74 const guint kNaClAlignmentMask = kNaClAlignmentMaskX86;
75
76 /* Default alignment for Native Client is 32-byte. */
77 gint8 nacl_align_byte = -32; /* signed version of 0xe0 */
78
79 /* mono_arch_nacl_pad: Add pad bytes of alignment instructions at code,       */
80 /* Check that alignment doesn't cross an alignment boundary.        */
81 guint8 *
82 mono_arch_nacl_pad (guint8 *code, int pad)
83 {
84         const int kMaxPadding = 7;    /* see x86-codegen.h: x86_padding() */
85
86         if (pad == 0) return code;
87         /* assertion: alignment cannot cross a block boundary */
88         g_assert(((uintptr_t)code & (~kNaClAlignmentMask)) ==
89                          (((uintptr_t)code + pad - 1) & (~kNaClAlignmentMask)));
90         while (pad >= kMaxPadding) {
91                 x86_padding (code, kMaxPadding);
92                 pad -= kMaxPadding;
93         }
94         if (pad != 0) x86_padding (code, pad);
95         return code;
96 }
97
98 guint8 *
99 mono_arch_nacl_skip_nops (guint8 *code)
100 {
101         x86_skip_nops (code);
102         return code;
103 }
104
105 #endif /* __native_client_codegen__ */
106
107 /*
108  * The code generated for sequence points reads from this location, which is
109  * made read-only when single stepping is enabled.
110  */
111 static gpointer ss_trigger_page;
112
113 /* Enabled breakpoints read from this trigger page */
114 static gpointer bp_trigger_page;
115
116 const char*
117 mono_arch_regname (int reg)
118 {
119         switch (reg) {
120         case X86_EAX: return "%eax";
121         case X86_EBX: return "%ebx";
122         case X86_ECX: return "%ecx";
123         case X86_EDX: return "%edx";
124         case X86_ESP: return "%esp";    
125         case X86_EBP: return "%ebp";
126         case X86_EDI: return "%edi";
127         case X86_ESI: return "%esi";
128         }
129         return "unknown";
130 }
131
132 const char*
133 mono_arch_fregname (int reg)
134 {
135         switch (reg) {
136         case 0:
137                 return "%fr0";
138         case 1:
139                 return "%fr1";
140         case 2:
141                 return "%fr2";
142         case 3:
143                 return "%fr3";
144         case 4:
145                 return "%fr4";
146         case 5:
147                 return "%fr5";
148         case 6:
149                 return "%fr6";
150         case 7:
151                 return "%fr7";
152         default:
153                 return "unknown";
154         }
155 }
156
157 const char *
158 mono_arch_xregname (int reg)
159 {
160         switch (reg) {
161         case 0:
162                 return "%xmm0";
163         case 1:
164                 return "%xmm1";
165         case 2:
166                 return "%xmm2";
167         case 3:
168                 return "%xmm3";
169         case 4:
170                 return "%xmm4";
171         case 5:
172                 return "%xmm5";
173         case 6:
174                 return "%xmm6";
175         case 7:
176                 return "%xmm7";
177         default:
178                 return "unknown";
179         }
180 }
181
182 void 
183 mono_x86_patch (unsigned char* code, gpointer target)
184 {
185         x86_patch (code, (unsigned char*)target);
186 }
187
188 typedef enum {
189         ArgInIReg,
190         ArgInFloatSSEReg,
191         ArgInDoubleSSEReg,
192         ArgOnStack,
193         ArgValuetypeInReg,
194         ArgOnFloatFpStack,
195         ArgOnDoubleFpStack,
196         ArgNone
197 } ArgStorage;
198
199 typedef struct {
200         gint16 offset;
201         gint8  reg;
202         ArgStorage storage;
203
204         /* Only if storage == ArgValuetypeInReg */
205         ArgStorage pair_storage [2];
206         gint8 pair_regs [2];
207 } ArgInfo;
208
209 typedef struct {
210         int nargs;
211         guint32 stack_usage;
212         guint32 reg_usage;
213         guint32 freg_usage;
214         gboolean need_stack_align;
215         guint32 stack_align_amount;
216         gboolean vtype_retaddr;
217         /* The index of the vret arg in the argument list */
218         int vret_arg_index;
219         ArgInfo ret;
220         ArgInfo sig_cookie;
221         ArgInfo args [1];
222 } CallInfo;
223
224 #define PARAM_REGS 0
225
226 #define FLOAT_PARAM_REGS 0
227
228 static X86_Reg_No param_regs [] = { 0 };
229
230 #if defined(TARGET_WIN32) || defined(__APPLE__) || defined(__FreeBSD__)
231 #define SMALL_STRUCTS_IN_REGS
232 static X86_Reg_No return_regs [] = { X86_EAX, X86_EDX };
233 #endif
234
235 static void inline
236 add_general (guint32 *gr, guint32 *stack_size, ArgInfo *ainfo)
237 {
238     ainfo->offset = *stack_size;
239
240     if (*gr >= PARAM_REGS) {
241                 ainfo->storage = ArgOnStack;
242                 (*stack_size) += sizeof (gpointer);
243     }
244     else {
245                 ainfo->storage = ArgInIReg;
246                 ainfo->reg = param_regs [*gr];
247                 (*gr) ++;
248     }
249 }
250
251 static void inline
252 add_general_pair (guint32 *gr, guint32 *stack_size, ArgInfo *ainfo)
253 {
254         ainfo->offset = *stack_size;
255
256         g_assert (PARAM_REGS == 0);
257         
258         ainfo->storage = ArgOnStack;
259         (*stack_size) += sizeof (gpointer) * 2;
260 }
261
262 static void inline
263 add_float (guint32 *gr, guint32 *stack_size, ArgInfo *ainfo, gboolean is_double)
264 {
265     ainfo->offset = *stack_size;
266
267     if (*gr >= FLOAT_PARAM_REGS) {
268                 ainfo->storage = ArgOnStack;
269                 (*stack_size) += is_double ? 8 : 4;
270     }
271     else {
272                 /* A double register */
273                 if (is_double)
274                         ainfo->storage = ArgInDoubleSSEReg;
275                 else
276                         ainfo->storage = ArgInFloatSSEReg;
277                 ainfo->reg = *gr;
278                 (*gr) += 1;
279     }
280 }
281
282
283 static void
284 add_valuetype (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type,
285                gboolean is_return,
286                guint32 *gr, guint32 *fr, guint32 *stack_size)
287 {
288         guint32 size;
289         MonoClass *klass;
290
291         klass = mono_class_from_mono_type (type);
292         size = mini_type_stack_size_full (gsctx, &klass->byval_arg, NULL, sig->pinvoke);
293
294 #ifdef SMALL_STRUCTS_IN_REGS
295         if (sig->pinvoke && is_return) {
296                 MonoMarshalType *info;
297
298                 /*
299                  * the exact rules are not very well documented, the code below seems to work with the 
300                  * code generated by gcc 3.3.3 -mno-cygwin.
301                  */
302                 info = mono_marshal_load_type_info (klass);
303                 g_assert (info);
304
305                 ainfo->pair_storage [0] = ainfo->pair_storage [1] = ArgNone;
306
307                 /* Special case structs with only a float member */
308                 if ((info->native_size == 8) && (info->num_fields == 1) && (info->fields [0].field->type->type == MONO_TYPE_R8)) {
309                         ainfo->storage = ArgValuetypeInReg;
310                         ainfo->pair_storage [0] = ArgOnDoubleFpStack;
311                         return;
312                 }
313                 if ((info->native_size == 4) && (info->num_fields == 1) && (info->fields [0].field->type->type == MONO_TYPE_R4)) {
314                         ainfo->storage = ArgValuetypeInReg;
315                         ainfo->pair_storage [0] = ArgOnFloatFpStack;
316                         return;
317                 }               
318                 if ((info->native_size == 1) || (info->native_size == 2) || (info->native_size == 4) || (info->native_size == 8)) {
319                         ainfo->storage = ArgValuetypeInReg;
320                         ainfo->pair_storage [0] = ArgInIReg;
321                         ainfo->pair_regs [0] = return_regs [0];
322                         if (info->native_size > 4) {
323                                 ainfo->pair_storage [1] = ArgInIReg;
324                                 ainfo->pair_regs [1] = return_regs [1];
325                         }
326                         return;
327                 }
328         }
329 #endif
330
331         ainfo->offset = *stack_size;
332         ainfo->storage = ArgOnStack;
333         *stack_size += ALIGN_TO (size, sizeof (gpointer));
334 }
335
336 /*
337  * get_call_info:
338  *
339  *  Obtain information about a call according to the calling convention.
340  * For x86 ELF, see the "System V Application Binary Interface Intel386 
341  * Architecture Processor Supplment, Fourth Edition" document for more
342  * information.
343  * For x86 win32, see ???.
344  */
345 static CallInfo*
346 get_call_info_internal (MonoGenericSharingContext *gsctx, CallInfo *cinfo, MonoMethodSignature *sig)
347 {
348         guint32 i, gr, fr, pstart;
349         MonoType *ret_type;
350         int n = sig->hasthis + sig->param_count;
351         guint32 stack_size = 0;
352         gboolean is_pinvoke = sig->pinvoke;
353
354         gr = 0;
355         fr = 0;
356
357         /* return value */
358         {
359                 ret_type = mini_type_get_underlying_type (gsctx, sig->ret);
360                 switch (ret_type->type) {
361                 case MONO_TYPE_BOOLEAN:
362                 case MONO_TYPE_I1:
363                 case MONO_TYPE_U1:
364                 case MONO_TYPE_I2:
365                 case MONO_TYPE_U2:
366                 case MONO_TYPE_CHAR:
367                 case MONO_TYPE_I4:
368                 case MONO_TYPE_U4:
369                 case MONO_TYPE_I:
370                 case MONO_TYPE_U:
371                 case MONO_TYPE_PTR:
372                 case MONO_TYPE_FNPTR:
373                 case MONO_TYPE_CLASS:
374                 case MONO_TYPE_OBJECT:
375                 case MONO_TYPE_SZARRAY:
376                 case MONO_TYPE_ARRAY:
377                 case MONO_TYPE_STRING:
378                         cinfo->ret.storage = ArgInIReg;
379                         cinfo->ret.reg = X86_EAX;
380                         break;
381                 case MONO_TYPE_U8:
382                 case MONO_TYPE_I8:
383                         cinfo->ret.storage = ArgInIReg;
384                         cinfo->ret.reg = X86_EAX;
385                         break;
386                 case MONO_TYPE_R4:
387                         cinfo->ret.storage = ArgOnFloatFpStack;
388                         break;
389                 case MONO_TYPE_R8:
390                         cinfo->ret.storage = ArgOnDoubleFpStack;
391                         break;
392                 case MONO_TYPE_GENERICINST:
393                         if (!mono_type_generic_inst_is_valuetype (ret_type)) {
394                                 cinfo->ret.storage = ArgInIReg;
395                                 cinfo->ret.reg = X86_EAX;
396                                 break;
397                         }
398                         /* Fall through */
399                 case MONO_TYPE_VALUETYPE: {
400                         guint32 tmp_gr = 0, tmp_fr = 0, tmp_stacksize = 0;
401
402                         add_valuetype (gsctx, sig, &cinfo->ret, sig->ret, TRUE, &tmp_gr, &tmp_fr, &tmp_stacksize);
403                         if (cinfo->ret.storage == ArgOnStack) {
404                                 cinfo->vtype_retaddr = TRUE;
405                                 /* The caller passes the address where the value is stored */
406                         }
407                         break;
408                 }
409                 case MONO_TYPE_TYPEDBYREF:
410                         /* Same as a valuetype with size 12 */
411                         cinfo->vtype_retaddr = TRUE;
412                         break;
413                 case MONO_TYPE_VOID:
414                         cinfo->ret.storage = ArgNone;
415                         break;
416                 default:
417                         g_error ("Can't handle as return value 0x%x", sig->ret->type);
418                 }
419         }
420
421         pstart = 0;
422         /*
423          * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
424          * the first argument, allowing 'this' to be always passed in the first arg reg.
425          * Also do this if the first argument is a reference type, since virtual calls
426          * are sometimes made using calli without sig->hasthis set, like in the delegate
427          * invoke wrappers.
428          */
429         if (cinfo->vtype_retaddr && !is_pinvoke && (sig->hasthis || (sig->param_count > 0 && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (gsctx, sig->params [0]))))) {
430                 if (sig->hasthis) {
431                         add_general (&gr, &stack_size, cinfo->args + 0);
432                 } else {
433                         add_general (&gr, &stack_size, &cinfo->args [sig->hasthis + 0]);
434                         pstart = 1;
435                 }
436                 add_general (&gr, &stack_size, &cinfo->ret);
437                 cinfo->vret_arg_index = 1;
438         } else {
439                 /* this */
440                 if (sig->hasthis)
441                         add_general (&gr, &stack_size, cinfo->args + 0);
442
443                 if (cinfo->vtype_retaddr)
444                         add_general (&gr, &stack_size, &cinfo->ret);
445         }
446
447         if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n == 0)) {
448                 gr = PARAM_REGS;
449                 fr = FLOAT_PARAM_REGS;
450                 
451                 /* Emit the signature cookie just before the implicit arguments */
452                 add_general (&gr, &stack_size, &cinfo->sig_cookie);
453         }
454
455         for (i = pstart; i < sig->param_count; ++i) {
456                 ArgInfo *ainfo = &cinfo->args [sig->hasthis + i];
457                 MonoType *ptype;
458
459                 if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) {
460                         /* We allways pass the sig cookie on the stack for simplicity */
461                         /* 
462                          * Prevent implicit arguments + the sig cookie from being passed 
463                          * in registers.
464                          */
465                         gr = PARAM_REGS;
466                         fr = FLOAT_PARAM_REGS;
467
468                         /* Emit the signature cookie just before the implicit arguments */
469                         add_general (&gr, &stack_size, &cinfo->sig_cookie);
470                 }
471
472                 if (sig->params [i]->byref) {
473                         add_general (&gr, &stack_size, ainfo);
474                         continue;
475                 }
476                 ptype = mini_type_get_underlying_type (gsctx, sig->params [i]);
477                 switch (ptype->type) {
478                 case MONO_TYPE_BOOLEAN:
479                 case MONO_TYPE_I1:
480                 case MONO_TYPE_U1:
481                         add_general (&gr, &stack_size, ainfo);
482                         break;
483                 case MONO_TYPE_I2:
484                 case MONO_TYPE_U2:
485                 case MONO_TYPE_CHAR:
486                         add_general (&gr, &stack_size, ainfo);
487                         break;
488                 case MONO_TYPE_I4:
489                 case MONO_TYPE_U4:
490                         add_general (&gr, &stack_size, ainfo);
491                         break;
492                 case MONO_TYPE_I:
493                 case MONO_TYPE_U:
494                 case MONO_TYPE_PTR:
495                 case MONO_TYPE_FNPTR:
496                 case MONO_TYPE_CLASS:
497                 case MONO_TYPE_OBJECT:
498                 case MONO_TYPE_STRING:
499                 case MONO_TYPE_SZARRAY:
500                 case MONO_TYPE_ARRAY:
501                         add_general (&gr, &stack_size, ainfo);
502                         break;
503                 case MONO_TYPE_GENERICINST:
504                         if (!mono_type_generic_inst_is_valuetype (ptype)) {
505                                 add_general (&gr, &stack_size, ainfo);
506                                 break;
507                         }
508                         /* Fall through */
509                 case MONO_TYPE_VALUETYPE:
510                         add_valuetype (gsctx, sig, ainfo, sig->params [i], FALSE, &gr, &fr, &stack_size);
511                         break;
512                 case MONO_TYPE_TYPEDBYREF:
513                         stack_size += sizeof (MonoTypedRef);
514                         ainfo->storage = ArgOnStack;
515                         break;
516                 case MONO_TYPE_U8:
517                 case MONO_TYPE_I8:
518                         add_general_pair (&gr, &stack_size, ainfo);
519                         break;
520                 case MONO_TYPE_R4:
521                         add_float (&fr, &stack_size, ainfo, FALSE);
522                         break;
523                 case MONO_TYPE_R8:
524                         add_float (&fr, &stack_size, ainfo, TRUE);
525                         break;
526                 default:
527                         g_error ("unexpected type 0x%x", ptype->type);
528                         g_assert_not_reached ();
529                 }
530         }
531
532         if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n > 0) && (sig->sentinelpos == sig->param_count)) {
533                 gr = PARAM_REGS;
534                 fr = FLOAT_PARAM_REGS;
535                 
536                 /* Emit the signature cookie just before the implicit arguments */
537                 add_general (&gr, &stack_size, &cinfo->sig_cookie);
538         }
539
540         if (mono_do_x86_stack_align && (stack_size % MONO_ARCH_FRAME_ALIGNMENT) != 0) {
541                 cinfo->need_stack_align = TRUE;
542                 cinfo->stack_align_amount = MONO_ARCH_FRAME_ALIGNMENT - (stack_size % MONO_ARCH_FRAME_ALIGNMENT);
543                 stack_size += cinfo->stack_align_amount;
544         }
545
546         cinfo->stack_usage = stack_size;
547         cinfo->reg_usage = gr;
548         cinfo->freg_usage = fr;
549         return cinfo;
550 }
551
552 static CallInfo*
553 get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSignature *sig)
554 {
555         int n = sig->hasthis + sig->param_count;
556         CallInfo *cinfo;
557
558         if (mp)
559                 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + (sizeof (ArgInfo) * n));
560         else
561                 cinfo = g_malloc0 (sizeof (CallInfo) + (sizeof (ArgInfo) * n));
562
563         return get_call_info_internal (gsctx, cinfo, sig);
564 }
565
566 /*
567  * mono_arch_get_argument_info:
568  * @csig:  a method signature
569  * @param_count: the number of parameters to consider
570  * @arg_info: an array to store the result infos
571  *
572  * Gathers information on parameters such as size, alignment and
573  * padding. arg_info should be large enought to hold param_count + 1 entries. 
574  *
575  * Returns the size of the argument area on the stack.
576  * This should be signal safe, since it is called from
577  * mono_arch_find_jit_info ().
578  * FIXME: The metadata calls might not be signal safe.
579  */
580 int
581 mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info)
582 {
583         int len, k, args_size = 0;
584         int size, pad;
585         guint32 align;
586         int offset = 8;
587         CallInfo *cinfo;
588
589         /* Avoid g_malloc as it is not signal safe */
590         len = sizeof (CallInfo) + (sizeof (ArgInfo) * (csig->param_count + 1));
591         cinfo = (CallInfo*)g_newa (guint8*, len);
592         memset (cinfo, 0, len);
593
594         cinfo = get_call_info_internal (NULL, cinfo, csig);
595
596         arg_info [0].offset = offset;
597
598         if (cinfo->vtype_retaddr && cinfo->vret_arg_index == 0) {
599                 args_size += sizeof (gpointer);
600                 offset += 4;
601         }
602
603         if (csig->hasthis) {
604                 args_size += sizeof (gpointer);
605                 offset += 4;
606         }
607
608         if (cinfo->vtype_retaddr && cinfo->vret_arg_index == 1 && csig->hasthis) {
609                 /* Emitted after this */
610                 args_size += sizeof (gpointer);
611                 offset += 4;
612         }
613
614         arg_info [0].size = args_size;
615
616         for (k = 0; k < param_count; k++) {
617                 size = mini_type_stack_size_full (NULL, csig->params [k], &align, csig->pinvoke);
618
619                 /* ignore alignment for now */
620                 align = 1;
621
622                 args_size += pad = (align - (args_size & (align - 1))) & (align - 1);   
623                 arg_info [k].pad = pad;
624                 args_size += size;
625                 arg_info [k + 1].pad = 0;
626                 arg_info [k + 1].size = size;
627                 offset += pad;
628                 arg_info [k + 1].offset = offset;
629                 offset += size;
630
631                 if (k == 0 && cinfo->vtype_retaddr && cinfo->vret_arg_index == 1 && !csig->hasthis) {
632                         /* Emitted after the first arg */
633                         args_size += sizeof (gpointer);
634                         offset += 4;
635                 }
636         }
637
638         if (mono_do_x86_stack_align && !CALLCONV_IS_STDCALL (csig))
639                 align = MONO_ARCH_FRAME_ALIGNMENT;
640         else
641                 align = 4;
642         args_size += pad = (align - (args_size & (align - 1))) & (align - 1);
643         arg_info [k].pad = pad;
644
645         return args_size;
646 }
647
648 gboolean
649 mono_x86_tail_call_supported (MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig)
650 {
651         CallInfo *c1, *c2;
652         gboolean res;
653
654         c1 = get_call_info (NULL, NULL, caller_sig);
655         c2 = get_call_info (NULL, NULL, callee_sig);
656         res = c1->stack_usage >= c2->stack_usage;
657         if (callee_sig->ret && MONO_TYPE_ISSTRUCT (callee_sig->ret) && c2->ret.storage != ArgValuetypeInReg)
658                 /* An address on the callee's stack is passed as the first argument */
659                 res = FALSE;
660
661         g_free (c1);
662         g_free (c2);
663
664         return res;
665 }
666
667 static const guchar cpuid_impl [] = {
668         0x55,                           /* push   %ebp */
669         0x89, 0xe5,                     /* mov    %esp,%ebp */
670         0x53,                           /* push   %ebx */
671         0x8b, 0x45, 0x08,               /* mov    0x8(%ebp),%eax */
672         0x0f, 0xa2,                     /* cpuid   */
673         0x50,                           /* push   %eax */
674         0x8b, 0x45, 0x10,               /* mov    0x10(%ebp),%eax */
675         0x89, 0x18,                     /* mov    %ebx,(%eax) */
676         0x8b, 0x45, 0x14,               /* mov    0x14(%ebp),%eax */
677         0x89, 0x08,                     /* mov    %ecx,(%eax) */
678         0x8b, 0x45, 0x18,               /* mov    0x18(%ebp),%eax */
679         0x89, 0x10,                     /* mov    %edx,(%eax) */
680         0x58,                           /* pop    %eax */
681         0x8b, 0x55, 0x0c,               /* mov    0xc(%ebp),%edx */
682         0x89, 0x02,                     /* mov    %eax,(%edx) */
683         0x5b,                           /* pop    %ebx */
684         0xc9,                           /* leave   */
685         0xc3,                           /* ret     */
686 };
687
688 typedef void (*CpuidFunc) (int id, int* p_eax, int* p_ebx, int* p_ecx, int* p_edx);
689
690 static int 
691 cpuid (int id, int* p_eax, int* p_ebx, int* p_ecx, int* p_edx)
692 {
693 #if defined(__native_client__)
694         /* Taken from below, the bug listed in the comment is */
695         /* only valid for non-static cases.                   */
696         __asm__ __volatile__ ("cpuid"
697                 : "=a" (*p_eax), "=b" (*p_ebx), "=c" (*p_ecx), "=d" (*p_edx)
698                 : "a" (id));
699         return 1;
700 #else
701         int have_cpuid = 0;
702 #ifndef _MSC_VER
703         __asm__  __volatile__ (
704                 "pushfl\n"
705                 "popl %%eax\n"
706                 "movl %%eax, %%edx\n"
707                 "xorl $0x200000, %%eax\n"
708                 "pushl %%eax\n"
709                 "popfl\n"
710                 "pushfl\n"
711                 "popl %%eax\n"
712                 "xorl %%edx, %%eax\n"
713                 "andl $0x200000, %%eax\n"
714                 "movl %%eax, %0"
715                 : "=r" (have_cpuid)
716                 :
717                 : "%eax", "%edx"
718         );
719 #else
720         __asm {
721                 pushfd
722                 pop eax
723                 mov edx, eax
724                 xor eax, 0x200000
725                 push eax
726                 popfd
727                 pushfd
728                 pop eax
729                 xor eax, edx
730                 and eax, 0x200000
731                 mov have_cpuid, eax
732         }
733 #endif
734         if (have_cpuid) {
735                 /* Have to use the code manager to get around WinXP DEP */
736                 static CpuidFunc func = NULL;
737                 void *ptr;
738                 if (!func) {
739                         ptr = mono_global_codeman_reserve (sizeof (cpuid_impl));
740                         memcpy (ptr, cpuid_impl, sizeof (cpuid_impl));
741                         func = (CpuidFunc)ptr;
742                 }
743                 func (id, p_eax, p_ebx, p_ecx, p_edx);
744
745                 /*
746                  * We use this approach because of issues with gcc and pic code, see:
747                  * http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=7329
748                 __asm__ __volatile__ ("cpuid"
749                         : "=a" (*p_eax), "=b" (*p_ebx), "=c" (*p_ecx), "=d" (*p_edx)
750                         : "a" (id));
751                 */
752                 return 1;
753         }
754         return 0;
755 #endif
756 }
757
758 /*
759  * Initialize the cpu to execute managed code.
760  */
761 void
762 mono_arch_cpu_init (void)
763 {
764         /* spec compliance requires running with double precision */
765 #ifndef _MSC_VER
766         guint16 fpcw;
767
768         __asm__  __volatile__ ("fnstcw %0\n": "=m" (fpcw));
769         fpcw &= ~X86_FPCW_PRECC_MASK;
770         fpcw |= X86_FPCW_PREC_DOUBLE;
771         __asm__  __volatile__ ("fldcw %0\n": : "m" (fpcw));
772         __asm__  __volatile__ ("fnstcw %0\n": "=m" (fpcw));
773 #else
774         _control87 (_PC_53, MCW_PC);
775 #endif
776 }
777
778 /*
779  * Initialize architecture specific code.
780  */
781 void
782 mono_arch_init (void)
783 {
784         InitializeCriticalSection (&mini_arch_mutex);
785
786         ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
787         bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
788         mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
789
790         mono_aot_register_jit_icall ("mono_x86_throw_exception", mono_x86_throw_exception);
791         mono_aot_register_jit_icall ("mono_x86_throw_corlib_exception", mono_x86_throw_corlib_exception);
792 }
793
794 /*
795  * Cleanup architecture specific code.
796  */
797 void
798 mono_arch_cleanup (void)
799 {
800         DeleteCriticalSection (&mini_arch_mutex);
801 }
802
803 /*
804  * This function returns the optimizations supported on this cpu.
805  */
806 guint32
807 mono_arch_cpu_optimizazions (guint32 *exclude_mask)
808 {
809 #if !defined(__native_client__)
810         int eax, ebx, ecx, edx;
811         guint32 opts = 0;
812         
813         *exclude_mask = 0;
814
815         if (mono_aot_only)
816                 /* The cpuid function allocates from the global codeman */
817                 return opts;
818
819         /* Feature Flags function, flags returned in EDX. */
820         if (cpuid (1, &eax, &ebx, &ecx, &edx)) {
821                 if (edx & (1 << 15)) {
822                         opts |= MONO_OPT_CMOV;
823                         if (edx & 1)
824                                 opts |= MONO_OPT_FCMOV;
825                         else
826                                 *exclude_mask |= MONO_OPT_FCMOV;
827                 } else
828                         *exclude_mask |= MONO_OPT_CMOV;
829                 if (edx & (1 << 26))
830                         opts |= MONO_OPT_SSE2;
831                 else
832                         *exclude_mask |= MONO_OPT_SSE2;
833
834 #ifdef MONO_ARCH_SIMD_INTRINSICS
835                 /*SIMD intrinsics require at least SSE2.*/
836                 if (!(opts & MONO_OPT_SSE2))
837                         *exclude_mask |= MONO_OPT_SIMD;
838 #endif
839         }
840         return opts;
841 #else
842         return MONO_OPT_CMOV | MONO_OPT_FCMOV | MONO_OPT_SSE2;
843 #endif
844 }
845
846 /*
847  * This function test for all SSE functions supported.
848  *
849  * Returns a bitmask corresponding to all supported versions.
850  * 
851  */
852 guint32
853 mono_arch_cpu_enumerate_simd_versions (void)
854 {
855         int eax, ebx, ecx, edx;
856         guint32 sse_opts = 0;
857
858         if (mono_aot_only)
859                 /* The cpuid function allocates from the global codeman */
860                 return sse_opts;
861
862         if (cpuid (1, &eax, &ebx, &ecx, &edx)) {
863                 if (edx & (1 << 25))
864                         sse_opts |= SIMD_VERSION_SSE1;
865                 if (edx & (1 << 26))
866                         sse_opts |= SIMD_VERSION_SSE2;
867                 if (ecx & (1 << 0))
868                         sse_opts |= SIMD_VERSION_SSE3;
869                 if (ecx & (1 << 9))
870                         sse_opts |= SIMD_VERSION_SSSE3;
871                 if (ecx & (1 << 19))
872                         sse_opts |= SIMD_VERSION_SSE41;
873                 if (ecx & (1 << 20))
874                         sse_opts |= SIMD_VERSION_SSE42;
875         }
876
877         /* Yes, all this needs to be done to check for sse4a.
878            See: "Amd: CPUID Specification"
879          */
880         if (cpuid (0x80000000, &eax, &ebx, &ecx, &edx)) {
881                 /* eax greater or equal than 0x80000001, ebx = 'htuA', ecx = DMAc', edx = 'itne'*/
882                 if ((((unsigned int) eax) >= 0x80000001) && (ebx == 0x68747541) && (ecx == 0x444D4163) && (edx == 0x69746E65)) {
883                         cpuid (0x80000001, &eax, &ebx, &ecx, &edx);
884                         if (ecx & (1 << 6))
885                                 sse_opts |= SIMD_VERSION_SSE4a;
886                 }
887         }
888
889
890         return sse_opts;        
891 }
892
893 /*
894  * Determine whenever the trap whose info is in SIGINFO is caused by
895  * integer overflow.
896  */
897 gboolean
898 mono_arch_is_int_overflow (void *sigctx, void *info)
899 {
900         MonoContext ctx;
901         guint8* ip;
902
903         mono_arch_sigctx_to_monoctx (sigctx, &ctx);
904
905         ip = (guint8*)ctx.eip;
906
907         if ((ip [0] == 0xf7) && (x86_modrm_mod (ip [1]) == 0x3) && (x86_modrm_reg (ip [1]) == 0x7)) {
908                 gint32 reg;
909
910                 /* idiv REG */
911                 switch (x86_modrm_rm (ip [1])) {
912                 case X86_EAX:
913                         reg = ctx.eax;
914                         break;
915                 case X86_ECX:
916                         reg = ctx.ecx;
917                         break;
918                 case X86_EDX:
919                         reg = ctx.edx;
920                         break;
921                 case X86_EBX:
922                         reg = ctx.ebx;
923                         break;
924                 case X86_ESI:
925                         reg = ctx.esi;
926                         break;
927                 case X86_EDI:
928                         reg = ctx.edi;
929                         break;
930                 default:
931                         g_assert_not_reached ();
932                         reg = -1;
933                 }
934
935                 if (reg == -1)
936                         return TRUE;
937         }
938                         
939         return FALSE;
940 }
941
942 GList *
943 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
944 {
945         GList *vars = NULL;
946         int i;
947
948         for (i = 0; i < cfg->num_varinfo; i++) {
949                 MonoInst *ins = cfg->varinfo [i];
950                 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
951
952                 /* unused vars */
953                 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
954                         continue;
955
956                 if ((ins->flags & (MONO_INST_IS_DEAD|MONO_INST_VOLATILE|MONO_INST_INDIRECT)) || 
957                     (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
958                         continue;
959
960                 /* we dont allocate I1 to registers because there is no simply way to sign extend 
961                  * 8bit quantities in caller saved registers on x86 */
962                 if (mono_is_regsize_var (ins->inst_vtype) && (ins->inst_vtype->type != MONO_TYPE_I1)) {
963                         g_assert (MONO_VARINFO (cfg, i)->reg == -1);
964                         g_assert (i == vmv->idx);
965                         vars = g_list_prepend (vars, vmv);
966                 }
967         }
968
969         vars = mono_varlist_sort (cfg, vars, 0);
970
971         return vars;
972 }
973
974 GList *
975 mono_arch_get_global_int_regs (MonoCompile *cfg)
976 {
977         GList *regs = NULL;
978
979         /* we can use 3 registers for global allocation */
980         regs = g_list_prepend (regs, (gpointer)X86_EBX);
981         regs = g_list_prepend (regs, (gpointer)X86_ESI);
982         regs = g_list_prepend (regs, (gpointer)X86_EDI);
983
984         return regs;
985 }
986
987 /*
988  * mono_arch_regalloc_cost:
989  *
990  *  Return the cost, in number of memory references, of the action of 
991  * allocating the variable VMV into a register during global register
992  * allocation.
993  */
994 guint32
995 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
996 {
997         MonoInst *ins = cfg->varinfo [vmv->idx];
998
999         if (cfg->method->save_lmf)
1000                 /* The register is already saved */
1001                 return (ins->opcode == OP_ARG) ? 1 : 0;
1002         else
1003                 /* push+pop+possible load if it is an argument */
1004                 return (ins->opcode == OP_ARG) ? 3 : 2;
1005 }
1006
1007 static void
1008 set_needs_stack_frame (MonoCompile *cfg, gboolean flag)
1009 {
1010         static int inited = FALSE;
1011         static int count = 0;
1012
1013         if (cfg->arch.need_stack_frame_inited) {
1014                 g_assert (cfg->arch.need_stack_frame == flag);
1015                 return;
1016         }
1017
1018         cfg->arch.need_stack_frame = flag;
1019         cfg->arch.need_stack_frame_inited = TRUE;
1020
1021         if (flag)
1022                 return;
1023
1024         if (!inited) {
1025                 mono_counters_register ("Could eliminate stack frame", MONO_COUNTER_INT|MONO_COUNTER_JIT, &count);
1026                 inited = TRUE;
1027         }
1028         ++count;
1029
1030         //g_print ("will eliminate %s.%s.%s\n", cfg->method->klass->name_space, cfg->method->klass->name, cfg->method->name);
1031 }
1032
1033 static gboolean
1034 needs_stack_frame (MonoCompile *cfg)
1035 {
1036         MonoMethodSignature *sig;
1037         MonoMethodHeader *header;
1038         gboolean result = FALSE;
1039
1040 #if defined(__APPLE__)
1041         /*OSX requires stack frame code to have the correct alignment. */
1042         return TRUE;
1043 #endif
1044
1045         if (cfg->arch.need_stack_frame_inited)
1046                 return cfg->arch.need_stack_frame;
1047
1048         header = cfg->header;
1049         sig = mono_method_signature (cfg->method);
1050
1051         if (cfg->disable_omit_fp)
1052                 result = TRUE;
1053         else if (cfg->flags & MONO_CFG_HAS_ALLOCA)
1054                 result = TRUE;
1055         else if (cfg->method->save_lmf)
1056                 result = TRUE;
1057         else if (cfg->stack_offset)
1058                 result = TRUE;
1059         else if (cfg->param_area)
1060                 result = TRUE;
1061         else if (cfg->flags & (MONO_CFG_HAS_CALLS | MONO_CFG_HAS_ALLOCA | MONO_CFG_HAS_TAIL))
1062                 result = TRUE;
1063         else if (header->num_clauses)
1064                 result = TRUE;
1065         else if (sig->param_count + sig->hasthis)
1066                 result = TRUE;
1067         else if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG))
1068                 result = TRUE;
1069         else if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method)) ||
1070                 (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
1071                 result = TRUE;
1072
1073         set_needs_stack_frame (cfg, result);
1074
1075         return cfg->arch.need_stack_frame;
1076 }
1077
1078 /*
1079  * Set var information according to the calling convention. X86 version.
1080  * The locals var stuff should most likely be split in another method.
1081  */
1082 void
1083 mono_arch_allocate_vars (MonoCompile *cfg)
1084 {
1085         MonoMethodSignature *sig;
1086         MonoMethodHeader *header;
1087         MonoInst *inst;
1088         guint32 locals_stack_size, locals_stack_align;
1089         int i, offset;
1090         gint32 *offsets;
1091         CallInfo *cinfo;
1092
1093         header = cfg->header;
1094         sig = mono_method_signature (cfg->method);
1095
1096         cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
1097
1098         cfg->frame_reg = X86_EBP;
1099         offset = 0;
1100
1101         /* Reserve space to save LMF and caller saved registers */
1102
1103         if (cfg->method->save_lmf) {
1104                 offset += sizeof (MonoLMF);
1105         } else {
1106                 if (cfg->used_int_regs & (1 << X86_EBX)) {
1107                         offset += 4;
1108                 }
1109
1110                 if (cfg->used_int_regs & (1 << X86_EDI)) {
1111                         offset += 4;
1112                 }
1113
1114                 if (cfg->used_int_regs & (1 << X86_ESI)) {
1115                         offset += 4;
1116                 }
1117         }
1118
1119         switch (cinfo->ret.storage) {
1120         case ArgValuetypeInReg:
1121                 /* Allocate a local to hold the result, the epilog will copy it to the correct place */
1122                 offset += 8;
1123                 cfg->ret->opcode = OP_REGOFFSET;
1124                 cfg->ret->inst_basereg = X86_EBP;
1125                 cfg->ret->inst_offset = - offset;
1126                 break;
1127         default:
1128                 break;
1129         }
1130
1131         /* Allocate locals */
1132         offsets = mono_allocate_stack_slots (cfg, TRUE, &locals_stack_size, &locals_stack_align);
1133         if (locals_stack_size > MONO_ARCH_MAX_FRAME_SIZE) {
1134                 char *mname = mono_method_full_name (cfg->method, TRUE);
1135                 cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
1136                 cfg->exception_message = g_strdup_printf ("Method %s stack is too big.", mname);
1137                 g_free (mname);
1138                 return;
1139         }
1140         if (locals_stack_align) {
1141                 offset += (locals_stack_align - 1);
1142                 offset &= ~(locals_stack_align - 1);
1143         }
1144         cfg->locals_min_stack_offset = - (offset + locals_stack_size);
1145         cfg->locals_max_stack_offset = - offset;
1146         /*
1147          * EBP is at alignment 8 % MONO_ARCH_FRAME_ALIGNMENT, so if we
1148          * have locals larger than 8 bytes we need to make sure that
1149          * they have the appropriate offset.
1150          */
1151         if (MONO_ARCH_FRAME_ALIGNMENT > 8 && locals_stack_align > 8)
1152                 offset += MONO_ARCH_FRAME_ALIGNMENT - sizeof (gpointer) * 2;
1153         for (i = cfg->locals_start; i < cfg->num_varinfo; i++) {
1154                 if (offsets [i] != -1) {
1155                         MonoInst *inst = cfg->varinfo [i];
1156                         inst->opcode = OP_REGOFFSET;
1157                         inst->inst_basereg = X86_EBP;
1158                         inst->inst_offset = - (offset + offsets [i]);
1159                         //printf ("allocated local %d to ", i); mono_print_tree_nl (inst);
1160                 }
1161         }
1162         offset += locals_stack_size;
1163
1164
1165         /*
1166          * Allocate arguments+return value
1167          */
1168
1169         switch (cinfo->ret.storage) {
1170         case ArgOnStack:
1171                 if (MONO_TYPE_ISSTRUCT (sig->ret)) {
1172                         /* 
1173                          * In the new IR, the cfg->vret_addr variable represents the
1174                          * vtype return value.
1175                          */
1176                         cfg->vret_addr->opcode = OP_REGOFFSET;
1177                         cfg->vret_addr->inst_basereg = cfg->frame_reg;
1178                         cfg->vret_addr->inst_offset = cinfo->ret.offset + ARGS_OFFSET;
1179                         if (G_UNLIKELY (cfg->verbose_level > 1)) {
1180                                 printf ("vret_addr =");
1181                                 mono_print_ins (cfg->vret_addr);
1182                         }
1183                 } else {
1184                         cfg->ret->opcode = OP_REGOFFSET;
1185                         cfg->ret->inst_basereg = X86_EBP;
1186                         cfg->ret->inst_offset = cinfo->ret.offset + ARGS_OFFSET;
1187                 }
1188                 break;
1189         case ArgValuetypeInReg:
1190                 break;
1191         case ArgInIReg:
1192                 cfg->ret->opcode = OP_REGVAR;
1193                 cfg->ret->inst_c0 = cinfo->ret.reg;
1194                 cfg->ret->dreg = cinfo->ret.reg;
1195                 break;
1196         case ArgNone:
1197         case ArgOnFloatFpStack:
1198         case ArgOnDoubleFpStack:
1199                 break;
1200         default:
1201                 g_assert_not_reached ();
1202         }
1203
1204         if (sig->call_convention == MONO_CALL_VARARG) {
1205                 g_assert (cinfo->sig_cookie.storage == ArgOnStack);
1206                 cfg->sig_cookie = cinfo->sig_cookie.offset + ARGS_OFFSET;
1207         }
1208
1209         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
1210                 ArgInfo *ainfo = &cinfo->args [i];
1211                 inst = cfg->args [i];
1212                 if (inst->opcode != OP_REGVAR) {
1213                         inst->opcode = OP_REGOFFSET;
1214                         inst->inst_basereg = X86_EBP;
1215                 }
1216                 inst->inst_offset = ainfo->offset + ARGS_OFFSET;
1217         }
1218
1219         cfg->stack_offset = offset;
1220 }
1221
1222 void
1223 mono_arch_create_vars (MonoCompile *cfg)
1224 {
1225         MonoMethodSignature *sig;
1226         CallInfo *cinfo;
1227
1228         sig = mono_method_signature (cfg->method);
1229
1230         cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
1231
1232         if (cinfo->ret.storage == ArgValuetypeInReg)
1233                 cfg->ret_var_is_local = TRUE;
1234         if ((cinfo->ret.storage != ArgValuetypeInReg) && MONO_TYPE_ISSTRUCT (sig->ret)) {
1235                 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
1236         }
1237 }
1238
1239 /*
1240  * It is expensive to adjust esp for each individual fp argument pushed on the stack
1241  * so we try to do it just once when we have multiple fp arguments in a row.
1242  * We don't use this mechanism generally because for int arguments the generated code
1243  * is slightly bigger and new generation cpus optimize away the dependency chains
1244  * created by push instructions on the esp value.
1245  * fp_arg_setup is the first argument in the execution sequence where the esp register
1246  * is modified.
1247  */
1248 static G_GNUC_UNUSED int
1249 collect_fp_stack_space (MonoMethodSignature *sig, int start_arg, int *fp_arg_setup)
1250 {
1251         int fp_space = 0;
1252         MonoType *t;
1253
1254         for (; start_arg < sig->param_count; ++start_arg) {
1255                 t = mini_type_get_underlying_type (NULL, sig->params [start_arg]);
1256                 if (!t->byref && t->type == MONO_TYPE_R8) {
1257                         fp_space += sizeof (double);
1258                         *fp_arg_setup = start_arg;
1259                 } else {
1260                         break;
1261                 }
1262         }
1263         return fp_space;
1264 }
1265
1266 static void
1267 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
1268 {
1269         MonoMethodSignature *tmp_sig;
1270
1271         /* FIXME: Add support for signature tokens to AOT */
1272         cfg->disable_aot = TRUE;
1273
1274         /*
1275          * mono_ArgIterator_Setup assumes the signature cookie is 
1276          * passed first and all the arguments which were before it are
1277          * passed on the stack after the signature. So compensate by 
1278          * passing a different signature.
1279          */
1280         tmp_sig = mono_metadata_signature_dup (call->signature);
1281         tmp_sig->param_count -= call->signature->sentinelpos;
1282         tmp_sig->sentinelpos = 0;
1283         memcpy (tmp_sig->params, call->signature->params + call->signature->sentinelpos, tmp_sig->param_count * sizeof (MonoType*));
1284
1285         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_X86_PUSH_IMM, -1, -1, tmp_sig);
1286 }
1287
1288 #ifdef ENABLE_LLVM
1289 LLVMCallInfo*
1290 mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
1291 {
1292         int i, n;
1293         CallInfo *cinfo;
1294         ArgInfo *ainfo;
1295         LLVMCallInfo *linfo;
1296         MonoType *t;
1297
1298         n = sig->param_count + sig->hasthis;
1299
1300         cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
1301
1302         linfo = mono_mempool_alloc0 (cfg->mempool, sizeof (LLVMCallInfo) + (sizeof (LLVMArgInfo) * n));
1303
1304         /*
1305          * LLVM always uses the native ABI while we use our own ABI, the
1306          * only difference is the handling of vtypes:
1307          * - we only pass/receive them in registers in some cases, and only 
1308          *   in 1 or 2 integer registers.
1309          */
1310         if (cinfo->ret.storage == ArgValuetypeInReg) {
1311                 if (sig->pinvoke) {
1312                         cfg->exception_message = g_strdup ("pinvoke + vtypes");
1313                         cfg->disable_llvm = TRUE;
1314                         return linfo;
1315                 }
1316
1317                 cfg->exception_message = g_strdup ("vtype ret in call");
1318                 cfg->disable_llvm = TRUE;
1319                 /*
1320                 linfo->ret.storage = LLVMArgVtypeInReg;
1321                 for (j = 0; j < 2; ++j)
1322                         linfo->ret.pair_storage [j] = arg_storage_to_llvm_arg_storage (cfg, cinfo->ret.pair_storage [j]);
1323                 */
1324         }
1325
1326         if (MONO_TYPE_ISSTRUCT (sig->ret) && cinfo->ret.storage == ArgInIReg) {
1327                 /* Vtype returned using a hidden argument */
1328                 linfo->ret.storage = LLVMArgVtypeRetAddr;
1329                 linfo->vret_arg_index = cinfo->vret_arg_index;
1330         }
1331
1332         if (MONO_TYPE_ISSTRUCT (sig->ret) && cinfo->ret.storage != ArgInIReg) {
1333                 // FIXME:
1334                 cfg->exception_message = g_strdup ("vtype ret in call");
1335                 cfg->disable_llvm = TRUE;
1336         }
1337
1338         for (i = 0; i < n; ++i) {
1339                 ainfo = cinfo->args + i;
1340
1341                 if (i >= sig->hasthis)
1342                         t = sig->params [i - sig->hasthis];
1343                 else
1344                         t = &mono_defaults.int_class->byval_arg;
1345
1346                 linfo->args [i].storage = LLVMArgNone;
1347
1348                 switch (ainfo->storage) {
1349                 case ArgInIReg:
1350                         linfo->args [i].storage = LLVMArgInIReg;
1351                         break;
1352                 case ArgInDoubleSSEReg:
1353                 case ArgInFloatSSEReg:
1354                         linfo->args [i].storage = LLVMArgInFPReg;
1355                         break;
1356                 case ArgOnStack:
1357                         if (MONO_TYPE_ISSTRUCT (t)) {
1358                                 if (mono_class_value_size (mono_class_from_mono_type (t), NULL) == 0)
1359                                 /* LLVM seems to allocate argument space for empty structures too */
1360                                         linfo->args [i].storage = LLVMArgNone;
1361                                 else
1362                                         linfo->args [i].storage = LLVMArgVtypeByVal;
1363                         } else {
1364                                 linfo->args [i].storage = LLVMArgInIReg;
1365                                 if (t->byref) {
1366                                         if (t->type == MONO_TYPE_R4)
1367                                                 linfo->args [i].storage = LLVMArgInFPReg;
1368                                         else if (t->type == MONO_TYPE_R8)
1369                                                 linfo->args [i].storage = LLVMArgInFPReg;
1370                                 }
1371                         }
1372                         break;
1373                 case ArgValuetypeInReg:
1374                         if (sig->pinvoke) {
1375                                 cfg->exception_message = g_strdup ("pinvoke + vtypes");
1376                                 cfg->disable_llvm = TRUE;
1377                                 return linfo;
1378                         }
1379
1380                         cfg->exception_message = g_strdup ("vtype arg");
1381                         cfg->disable_llvm = TRUE;
1382                         /*
1383                         linfo->args [i].storage = LLVMArgVtypeInReg;
1384                         for (j = 0; j < 2; ++j)
1385                                 linfo->args [i].pair_storage [j] = arg_storage_to_llvm_arg_storage (cfg, ainfo->pair_storage [j]);
1386                         */
1387                         break;
1388                 default:
1389                         cfg->exception_message = g_strdup ("ainfo->storage");
1390                         cfg->disable_llvm = TRUE;
1391                         break;
1392                 }
1393         }
1394
1395         return linfo;
1396 }
1397 #endif
1398
1399 void
1400 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
1401 {
1402         MonoInst *arg, *in;
1403         MonoMethodSignature *sig;
1404         int i, n;
1405         CallInfo *cinfo;
1406         int sentinelpos = 0;
1407
1408         sig = call->signature;
1409         n = sig->param_count + sig->hasthis;
1410
1411         cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
1412
1413         if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG))
1414                 sentinelpos = sig->sentinelpos + (sig->hasthis ? 1 : 0);
1415
1416         if (cinfo->need_stack_align) {
1417                 MONO_INST_NEW (cfg, arg, OP_SUB_IMM);
1418                 arg->dreg = X86_ESP;
1419                 arg->sreg1 = X86_ESP;
1420                 arg->inst_imm = cinfo->stack_align_amount;
1421                 MONO_ADD_INS (cfg->cbb, arg);
1422         }
1423
1424         if (sig->ret && MONO_TYPE_ISSTRUCT (sig->ret)) {
1425                 if (cinfo->ret.storage == ArgValuetypeInReg) {
1426                         /*
1427                          * Tell the JIT to use a more efficient calling convention: call using
1428                          * OP_CALL, compute the result location after the call, and save the 
1429                          * result there.
1430                          */
1431                         call->vret_in_reg = TRUE;
1432                         if (call->vret_var)
1433                                 NULLIFY_INS (call->vret_var);
1434                 }
1435         }
1436
1437         /* Handle the case where there are no implicit arguments */
1438         if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n == sentinelpos)) {
1439                 emit_sig_cookie (cfg, call, cinfo);
1440         }
1441
1442         /* Arguments are pushed in the reverse order */
1443         for (i = n - 1; i >= 0; i --) {
1444                 ArgInfo *ainfo = cinfo->args + i;
1445                 MonoType *t;
1446
1447                 if (cinfo->vtype_retaddr && cinfo->vret_arg_index == 1 && i == 0) {
1448                         /* Push the vret arg before the first argument */
1449                         MonoInst *vtarg;
1450                         MONO_INST_NEW (cfg, vtarg, OP_X86_PUSH);
1451                         vtarg->type = STACK_MP;
1452                         vtarg->sreg1 = call->vret_var->dreg;
1453                         MONO_ADD_INS (cfg->cbb, vtarg);
1454                 }
1455
1456                 if (i >= sig->hasthis)
1457                         t = sig->params [i - sig->hasthis];
1458                 else
1459                         t = &mono_defaults.int_class->byval_arg;
1460                 t = mini_type_get_underlying_type (cfg->generic_sharing_context, t);
1461
1462                 MONO_INST_NEW (cfg, arg, OP_X86_PUSH);
1463
1464                 in = call->args [i];
1465                 arg->cil_code = in->cil_code;
1466                 arg->sreg1 = in->dreg;
1467                 arg->type = in->type;
1468
1469                 g_assert (in->dreg != -1);
1470
1471                 if ((i >= sig->hasthis) && (MONO_TYPE_ISSTRUCT(t))) {
1472                         guint32 align;
1473                         guint32 size;
1474
1475                         g_assert (in->klass);
1476
1477                         if (t->type == MONO_TYPE_TYPEDBYREF) {
1478                                 size = sizeof (MonoTypedRef);
1479                                 align = sizeof (gpointer);
1480                         }
1481                         else {
1482                                 size = mini_type_stack_size_full (cfg->generic_sharing_context, &in->klass->byval_arg, &align, sig->pinvoke);
1483                         }
1484
1485                         if (size > 0) {
1486                                 arg->opcode = OP_OUTARG_VT;
1487                                 arg->sreg1 = in->dreg;
1488                                 arg->klass = in->klass;
1489                                 arg->backend.size = size;
1490
1491                                 MONO_ADD_INS (cfg->cbb, arg);
1492                         }
1493                 }
1494                 else {
1495                         switch (ainfo->storage) {
1496                         case ArgOnStack:
1497                                 arg->opcode = OP_X86_PUSH;
1498                                 if (!t->byref) {
1499                                         if (t->type == MONO_TYPE_R4) {
1500                                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, 4);
1501                                                 arg->opcode = OP_STORER4_MEMBASE_REG;
1502                                                 arg->inst_destbasereg = X86_ESP;
1503                                                 arg->inst_offset = 0;
1504                                         } else if (t->type == MONO_TYPE_R8) {
1505                                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, 8);
1506                                                 arg->opcode = OP_STORER8_MEMBASE_REG;
1507                                                 arg->inst_destbasereg = X86_ESP;
1508                                                 arg->inst_offset = 0;
1509                                         } else if (t->type == MONO_TYPE_I8 || t->type == MONO_TYPE_U8) {
1510                                                 arg->sreg1 ++;
1511                                                 MONO_EMIT_NEW_UNALU (cfg, OP_X86_PUSH, -1, in->dreg + 2);
1512                                         }
1513                                 }
1514                                 break;
1515                         default:
1516                                 g_assert_not_reached ();
1517                         }
1518                         
1519                         MONO_ADD_INS (cfg->cbb, arg);
1520                 }
1521
1522                 if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (i == sentinelpos)) {
1523                         /* Emit the signature cookie just before the implicit arguments */
1524                         emit_sig_cookie (cfg, call, cinfo);
1525                 }
1526         }
1527
1528         if (sig->ret && MONO_TYPE_ISSTRUCT (sig->ret)) {
1529                 MonoInst *vtarg;
1530
1531                 if (cinfo->ret.storage == ArgValuetypeInReg) {
1532                         /* Already done */
1533                 }
1534                 else if (cinfo->ret.storage == ArgInIReg) {
1535                         NOT_IMPLEMENTED;
1536                         /* The return address is passed in a register */
1537                         MONO_INST_NEW (cfg, vtarg, OP_MOVE);
1538                         vtarg->sreg1 = call->inst.dreg;
1539                         vtarg->dreg = mono_alloc_ireg (cfg);
1540                         MONO_ADD_INS (cfg->cbb, vtarg);
1541                                 
1542                         mono_call_inst_add_outarg_reg (cfg, call, vtarg->dreg, cinfo->ret.reg, FALSE);
1543                 } else if (cinfo->vtype_retaddr && cinfo->vret_arg_index == 0) {
1544                         MonoInst *vtarg;
1545                         MONO_INST_NEW (cfg, vtarg, OP_X86_PUSH);
1546                         vtarg->type = STACK_MP;
1547                         vtarg->sreg1 = call->vret_var->dreg;
1548                         MONO_ADD_INS (cfg->cbb, vtarg);
1549                 }
1550
1551                 /* if the function returns a struct on stack, the called method already does a ret $0x4 */
1552                 if (cinfo->ret.storage != ArgValuetypeInReg)
1553                         cinfo->stack_usage -= 4;
1554         }
1555
1556         call->stack_usage = cinfo->stack_usage;
1557 }
1558
1559 void
1560 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
1561 {
1562         MonoInst *arg;
1563         int size = ins->backend.size;
1564
1565         if (size <= 4) {
1566                 MONO_INST_NEW (cfg, arg, OP_X86_PUSH_MEMBASE);
1567                 arg->sreg1 = src->dreg;
1568
1569                 MONO_ADD_INS (cfg->cbb, arg);
1570         } else if (size <= 20) {        
1571                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, ALIGN_TO (size, 4));
1572                 mini_emit_memcpy (cfg, X86_ESP, 0, src->dreg, 0, size, 4);
1573         } else {
1574                 MONO_INST_NEW (cfg, arg, OP_X86_PUSH_OBJ);
1575                 arg->inst_basereg = src->dreg;
1576                 arg->inst_offset = 0;
1577                 arg->inst_imm = size;
1578                                         
1579                 MONO_ADD_INS (cfg->cbb, arg);
1580         }
1581 }
1582
1583 void
1584 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
1585 {
1586         MonoType *ret = mini_type_get_underlying_type (cfg->generic_sharing_context, mono_method_signature (method)->ret);
1587
1588         if (!ret->byref) {
1589                 if (ret->type == MONO_TYPE_R4) {
1590                         if (COMPILE_LLVM (cfg))
1591                                 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
1592                         /* Nothing to do */
1593                         return;
1594                 } else if (ret->type == MONO_TYPE_R8) {
1595                         if (COMPILE_LLVM (cfg))
1596                                 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
1597                         /* Nothing to do */
1598                         return;
1599                 } else if (ret->type == MONO_TYPE_I8 || ret->type == MONO_TYPE_U8) {
1600                         if (COMPILE_LLVM (cfg))
1601                                 MONO_EMIT_NEW_UNALU (cfg, OP_LMOVE, cfg->ret->dreg, val->dreg);
1602                         else {
1603                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, X86_EAX, val->dreg + 1);
1604                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, X86_EDX, val->dreg + 2);
1605                         }
1606                         return;
1607                 }
1608         }
1609                         
1610         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
1611 }
1612
1613 /*
1614  * Allow tracing to work with this interface (with an optional argument)
1615  */
1616 void*
1617 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments)
1618 {
1619         guchar *code = p;
1620
1621         g_assert (MONO_ARCH_FRAME_ALIGNMENT >= 8);
1622         x86_alu_reg_imm (code, X86_SUB, X86_ESP, MONO_ARCH_FRAME_ALIGNMENT - 8);
1623
1624         /* if some args are passed in registers, we need to save them here */
1625         x86_push_reg (code, X86_EBP);
1626
1627         if (cfg->compile_aot) {
1628                 x86_push_imm (code, cfg->method);
1629                 x86_mov_reg_imm (code, X86_EAX, func);
1630                 x86_call_reg (code, X86_EAX);
1631         } else {
1632                 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_METHODCONST, cfg->method);
1633                 x86_push_imm (code, cfg->method);
1634                 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_ABS, func);
1635                 x86_call_code (code, 0);
1636         }
1637         x86_alu_reg_imm (code, X86_ADD, X86_ESP, MONO_ARCH_FRAME_ALIGNMENT);
1638
1639         return code;
1640 }
1641
1642 enum {
1643         SAVE_NONE,
1644         SAVE_STRUCT,
1645         SAVE_EAX,
1646         SAVE_EAX_EDX,
1647         SAVE_FP
1648 };
1649
1650 void*
1651 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
1652 {
1653         guchar *code = p;
1654         int arg_size = 0, stack_usage = 0, save_mode = SAVE_NONE;
1655         MonoMethod *method = cfg->method;
1656         MonoType *ret_type = mini_type_get_underlying_type (cfg->generic_sharing_context, mono_method_signature (method)->ret);
1657
1658         switch (ret_type->type) {
1659         case MONO_TYPE_VOID:
1660                 /* special case string .ctor icall */
1661                 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class) {
1662                         save_mode = SAVE_EAX;
1663                         stack_usage = enable_arguments ? 8 : 4;
1664                 } else
1665                         save_mode = SAVE_NONE;
1666                 break;
1667         case MONO_TYPE_I8:
1668         case MONO_TYPE_U8:
1669                 save_mode = SAVE_EAX_EDX;
1670                 stack_usage = enable_arguments ? 16 : 8;
1671                 break;
1672         case MONO_TYPE_R4:
1673         case MONO_TYPE_R8:
1674                 save_mode = SAVE_FP;
1675                 stack_usage = enable_arguments ? 16 : 8;
1676                 break;
1677         case MONO_TYPE_GENERICINST:
1678                 if (!mono_type_generic_inst_is_valuetype (ret_type)) {
1679                         save_mode = SAVE_EAX;
1680                         stack_usage = enable_arguments ? 8 : 4;
1681                         break;
1682                 }
1683                 /* Fall through */
1684         case MONO_TYPE_VALUETYPE:
1685                 // FIXME: Handle SMALL_STRUCT_IN_REG here for proper alignment on darwin-x86
1686                 save_mode = SAVE_STRUCT;
1687                 stack_usage = enable_arguments ? 4 : 0;
1688                 break;
1689         default:
1690                 save_mode = SAVE_EAX;
1691                 stack_usage = enable_arguments ? 8 : 4;
1692                 break;
1693         }
1694
1695         x86_alu_reg_imm (code, X86_SUB, X86_ESP, MONO_ARCH_FRAME_ALIGNMENT - stack_usage - 4);
1696
1697         switch (save_mode) {
1698         case SAVE_EAX_EDX:
1699                 x86_push_reg (code, X86_EDX);
1700                 x86_push_reg (code, X86_EAX);
1701                 if (enable_arguments) {
1702                         x86_push_reg (code, X86_EDX);
1703                         x86_push_reg (code, X86_EAX);
1704                         arg_size = 8;
1705                 }
1706                 break;
1707         case SAVE_EAX:
1708                 x86_push_reg (code, X86_EAX);
1709                 if (enable_arguments) {
1710                         x86_push_reg (code, X86_EAX);
1711                         arg_size = 4;
1712                 }
1713                 break;
1714         case SAVE_FP:
1715                 x86_alu_reg_imm (code, X86_SUB, X86_ESP, 8);
1716                 x86_fst_membase (code, X86_ESP, 0, TRUE, TRUE);
1717                 if (enable_arguments) {
1718                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, 8);
1719                         x86_fst_membase (code, X86_ESP, 0, TRUE, TRUE);
1720                         arg_size = 8;
1721                 }
1722                 break;
1723         case SAVE_STRUCT:
1724                 if (enable_arguments) {
1725                         x86_push_membase (code, X86_EBP, 8);
1726                         arg_size = 4;
1727                 }
1728                 break;
1729         case SAVE_NONE:
1730         default:
1731                 break;
1732         }
1733
1734         if (cfg->compile_aot) {
1735                 x86_push_imm (code, method);
1736                 x86_mov_reg_imm (code, X86_EAX, func);
1737                 x86_call_reg (code, X86_EAX);
1738         } else {
1739                 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_METHODCONST, method);
1740                 x86_push_imm (code, method);
1741                 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_ABS, func);
1742                 x86_call_code (code, 0);
1743         }
1744
1745         x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size + 4);
1746
1747         switch (save_mode) {
1748         case SAVE_EAX_EDX:
1749                 x86_pop_reg (code, X86_EAX);
1750                 x86_pop_reg (code, X86_EDX);
1751                 break;
1752         case SAVE_EAX:
1753                 x86_pop_reg (code, X86_EAX);
1754                 break;
1755         case SAVE_FP:
1756                 x86_fld_membase (code, X86_ESP, 0, TRUE);
1757                 x86_alu_reg_imm (code, X86_ADD, X86_ESP, 8);
1758                 break;
1759         case SAVE_NONE:
1760         default:
1761                 break;
1762         }
1763         
1764         x86_alu_reg_imm (code, X86_ADD, X86_ESP, MONO_ARCH_FRAME_ALIGNMENT - stack_usage);
1765
1766         return code;
1767 }
1768
1769 #define EMIT_COND_BRANCH(ins,cond,sign) \
1770 if (ins->inst_true_bb->native_offset) { \
1771         x86_branch (code, cond, cfg->native_code + ins->inst_true_bb->native_offset, sign); \
1772 } else { \
1773         mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); \
1774         if ((cfg->opt & MONO_OPT_BRANCH) && \
1775             x86_is_imm8 (ins->inst_true_bb->max_offset - cpos)) \
1776                 x86_branch8 (code, cond, 0, sign); \
1777         else \
1778                 x86_branch32 (code, cond, 0, sign); \
1779 }
1780
1781 /*  
1782  *      Emit an exception if condition is fail and
1783  *  if possible do a directly branch to target 
1784  */
1785 #define EMIT_COND_SYSTEM_EXCEPTION(cond,signed,exc_name)            \
1786         do {                                                        \
1787                 MonoInst *tins = mono_branch_optimize_exception_target (cfg, bb, exc_name); \
1788                 if (tins == NULL) {                                                                             \
1789                         mono_add_patch_info (cfg, code - cfg->native_code,   \
1790                                         MONO_PATCH_INFO_EXC, exc_name);  \
1791                         x86_branch32 (code, cond, 0, signed);               \
1792                 } else {        \
1793                         EMIT_COND_BRANCH (tins, cond, signed);  \
1794                 }                       \
1795         } while (0); 
1796
1797 #define EMIT_FPCOMPARE(code) do { \
1798         x86_fcompp (code); \
1799         x86_fnstsw (code); \
1800 } while (0); 
1801
1802
1803 static guint8*
1804 emit_call (MonoCompile *cfg, guint8 *code, guint32 patch_type, gconstpointer data)
1805 {
1806         gboolean needs_paddings = TRUE;
1807         guint32 pad_size;
1808
1809         if (cfg->abs_patches && g_hash_table_lookup (cfg->abs_patches, data)) {
1810         } else {
1811                 MonoJitICallInfo *info = mono_find_jit_icall_by_addr (data);
1812                 if (info) {
1813                         if ((cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) && strstr (cfg->method->name, info->name))
1814                                 needs_paddings = FALSE; /* A call to the wrapped function */
1815                 }
1816         }
1817
1818         if (cfg->compile_aot)
1819                 needs_paddings = FALSE;
1820         /*The address must be 4 bytes aligned to avoid spanning multiple cache lines.
1821         This is required for code patching to be safe on SMP machines.
1822         */
1823         pad_size = (guint32)(code + 1 - cfg->native_code) & 0x3;
1824         if (needs_paddings && pad_size)
1825                 x86_padding (code, pad_size);
1826
1827         mono_add_patch_info (cfg, code - cfg->native_code, patch_type, data);
1828         x86_call_code (code, 0);
1829
1830         return code;
1831 }
1832
1833 #define INST_IGNORES_CFLAGS(opcode) (!(((opcode) == OP_ADC) || ((opcode) == OP_IADC) || ((opcode) == OP_ADC_IMM) || ((opcode) == OP_IADC_IMM) || ((opcode) == OP_SBB) || ((opcode) == OP_ISBB) || ((opcode) == OP_SBB_IMM) || ((opcode) == OP_ISBB_IMM)))
1834
1835 /*
1836  * mono_peephole_pass_1:
1837  *
1838  *   Perform peephole opts which should/can be performed before local regalloc
1839  */
1840 void
1841 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
1842 {
1843         MonoInst *ins, *n;
1844
1845         MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
1846                 MonoInst *last_ins = ins->prev;
1847
1848                 switch (ins->opcode) {
1849                 case OP_IADD_IMM:
1850                 case OP_ADD_IMM:
1851                         if ((ins->sreg1 < MONO_MAX_IREGS) && (ins->dreg >= MONO_MAX_IREGS)) {
1852                                 /* 
1853                                  * X86_LEA is like ADD, but doesn't have the
1854                                  * sreg1==dreg restriction.
1855                                  */
1856                                 ins->opcode = OP_X86_LEA_MEMBASE;
1857                                 ins->inst_basereg = ins->sreg1;
1858                         } else if ((ins->inst_imm == 1) && (ins->dreg == ins->sreg1))
1859                                 ins->opcode = OP_X86_INC_REG;
1860                         break;
1861                 case OP_SUB_IMM:
1862                 case OP_ISUB_IMM:
1863                         if ((ins->sreg1 < MONO_MAX_IREGS) && (ins->dreg >= MONO_MAX_IREGS)) {
1864                                 ins->opcode = OP_X86_LEA_MEMBASE;
1865                                 ins->inst_basereg = ins->sreg1;
1866                                 ins->inst_imm = -ins->inst_imm;
1867                         } else if ((ins->inst_imm == 1) && (ins->dreg == ins->sreg1))
1868                                 ins->opcode = OP_X86_DEC_REG;
1869                         break;
1870                 case OP_COMPARE_IMM:
1871                 case OP_ICOMPARE_IMM:
1872                         /* OP_COMPARE_IMM (reg, 0) 
1873                          * --> 
1874                          * OP_X86_TEST_NULL (reg) 
1875                          */
1876                         if (!ins->inst_imm)
1877                                 ins->opcode = OP_X86_TEST_NULL;
1878                         break;
1879                 case OP_X86_COMPARE_MEMBASE_IMM:
1880                         /* 
1881                          * OP_STORE_MEMBASE_REG reg, offset(basereg)
1882                          * OP_X86_COMPARE_MEMBASE_IMM offset(basereg), imm
1883                          * -->
1884                          * OP_STORE_MEMBASE_REG reg, offset(basereg)
1885                          * OP_COMPARE_IMM reg, imm
1886                          *
1887                          * Note: if imm = 0 then OP_COMPARE_IMM replaced with OP_X86_TEST_NULL
1888                          */
1889                         if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG) &&
1890                             ins->inst_basereg == last_ins->inst_destbasereg &&
1891                             ins->inst_offset == last_ins->inst_offset) {
1892                                         ins->opcode = OP_COMPARE_IMM;
1893                                         ins->sreg1 = last_ins->sreg1;
1894
1895                                         /* check if we can remove cmp reg,0 with test null */
1896                                         if (!ins->inst_imm)
1897                                                 ins->opcode = OP_X86_TEST_NULL;
1898                                 }
1899
1900                         break;                  
1901                 case OP_X86_PUSH_MEMBASE:
1902                         if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG ||
1903                                          last_ins->opcode == OP_STORE_MEMBASE_REG) &&
1904                             ins->inst_basereg == last_ins->inst_destbasereg &&
1905                             ins->inst_offset == last_ins->inst_offset) {
1906                                     ins->opcode = OP_X86_PUSH;
1907                                     ins->sreg1 = last_ins->sreg1;
1908                         }
1909                         break;
1910                 }
1911
1912                 mono_peephole_ins (bb, ins);
1913         }
1914 }
1915
1916 void
1917 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
1918 {
1919         MonoInst *ins, *n;
1920
1921         MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
1922                 switch (ins->opcode) {
1923                 case OP_ICONST:
1924                         /* reg = 0 -> XOR (reg, reg) */
1925                         /* XOR sets cflags on x86, so we cant do it always */
1926                         if (ins->inst_c0 == 0 && (!ins->next || (ins->next && INST_IGNORES_CFLAGS (ins->next->opcode)))) {
1927                                 MonoInst *ins2;
1928
1929                                 ins->opcode = OP_IXOR;
1930                                 ins->sreg1 = ins->dreg;
1931                                 ins->sreg2 = ins->dreg;
1932
1933                                 /* 
1934                                  * Convert succeeding STORE_MEMBASE_IMM 0 ins to STORE_MEMBASE_REG 
1935                                  * since it takes 3 bytes instead of 7.
1936                                  */
1937                                 for (ins2 = ins->next; ins2; ins2 = ins2->next) {
1938                                         if ((ins2->opcode == OP_STORE_MEMBASE_IMM) && (ins2->inst_imm == 0)) {
1939                                                 ins2->opcode = OP_STORE_MEMBASE_REG;
1940                                                 ins2->sreg1 = ins->dreg;
1941                                         }
1942                                         else if ((ins2->opcode == OP_STOREI4_MEMBASE_IMM) && (ins2->inst_imm == 0)) {
1943                                                 ins2->opcode = OP_STOREI4_MEMBASE_REG;
1944                                                 ins2->sreg1 = ins->dreg;
1945                                         }
1946                                         else if ((ins2->opcode == OP_STOREI1_MEMBASE_IMM) || (ins2->opcode == OP_STOREI2_MEMBASE_IMM)) {
1947                                                 /* Continue iteration */
1948                                         }
1949                                         else
1950                                                 break;
1951                                 }
1952                         }
1953                         break;
1954                 case OP_IADD_IMM:
1955                 case OP_ADD_IMM:
1956                         if ((ins->inst_imm == 1) && (ins->dreg == ins->sreg1))
1957                                 ins->opcode = OP_X86_INC_REG;
1958                         break;
1959                 case OP_ISUB_IMM:
1960                 case OP_SUB_IMM:
1961                         if ((ins->inst_imm == 1) && (ins->dreg == ins->sreg1))
1962                                 ins->opcode = OP_X86_DEC_REG;
1963                         break;
1964                 }
1965
1966                 mono_peephole_ins (bb, ins);
1967         }
1968 }
1969
1970 /*
1971  * mono_arch_lowering_pass:
1972  *
1973  *  Converts complex opcodes into simpler ones so that each IR instruction
1974  * corresponds to one machine instruction.
1975  */
1976 void
1977 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
1978 {
1979         MonoInst *ins, *next;
1980
1981         /*
1982          * FIXME: Need to add more instructions, but the current machine 
1983          * description can't model some parts of the composite instructions like
1984          * cdq.
1985          */
1986         MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
1987                 switch (ins->opcode) {
1988                 case OP_IREM_IMM:
1989                 case OP_IDIV_IMM:
1990                 case OP_IDIV_UN_IMM:
1991                 case OP_IREM_UN_IMM:
1992                         /* 
1993                          * Keep the cases where we could generated optimized code, otherwise convert
1994                          * to the non-imm variant.
1995                          */
1996                         if ((ins->opcode == OP_IREM_IMM) && mono_is_power_of_two (ins->inst_imm) >= 0)
1997                                 break;
1998                         mono_decompose_op_imm (cfg, bb, ins);
1999                         break;
2000                 default:
2001                         break;
2002                 }
2003         }
2004
2005         bb->max_vreg = cfg->next_vreg;
2006 }
2007
2008 static const int 
2009 branch_cc_table [] = {
2010         X86_CC_EQ, X86_CC_GE, X86_CC_GT, X86_CC_LE, X86_CC_LT,
2011         X86_CC_NE, X86_CC_GE, X86_CC_GT, X86_CC_LE, X86_CC_LT,
2012         X86_CC_O, X86_CC_NO, X86_CC_C, X86_CC_NC
2013 };
2014
2015 /* Maps CMP_... constants to X86_CC_... constants */
2016 static const int
2017 cc_table [] = {
2018         X86_CC_EQ, X86_CC_NE, X86_CC_LE, X86_CC_GE, X86_CC_LT, X86_CC_GT,
2019         X86_CC_LE, X86_CC_GE, X86_CC_LT, X86_CC_GT
2020 };
2021
2022 static const int
2023 cc_signed_table [] = {
2024         TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
2025         FALSE, FALSE, FALSE, FALSE
2026 };
2027
2028 static unsigned char*
2029 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int size, gboolean is_signed)
2030 {
2031 #define XMM_TEMP_REG 0
2032         /*This SSE2 optimization must not be done which OPT_SIMD in place as it clobbers xmm0.*/
2033         /*The xmm pass decomposes OP_FCONV_ ops anyway anyway.*/
2034         if (cfg->opt & MONO_OPT_SSE2 && size < 8 && !(cfg->opt & MONO_OPT_SIMD)) {
2035                 /* optimize by assigning a local var for this use so we avoid
2036                  * the stack manipulations */
2037                 x86_alu_reg_imm (code, X86_SUB, X86_ESP, 8);
2038                 x86_fst_membase (code, X86_ESP, 0, TRUE, TRUE);
2039                 x86_movsd_reg_membase (code, XMM_TEMP_REG, X86_ESP, 0);
2040                 x86_cvttsd2si (code, dreg, XMM_TEMP_REG);
2041                 x86_alu_reg_imm (code, X86_ADD, X86_ESP, 8);
2042                 if (size == 1)
2043                         x86_widen_reg (code, dreg, dreg, is_signed, FALSE);
2044                 else if (size == 2)
2045                         x86_widen_reg (code, dreg, dreg, is_signed, TRUE);
2046                 return code;
2047         }
2048         x86_alu_reg_imm (code, X86_SUB, X86_ESP, 4);
2049         x86_fnstcw_membase(code, X86_ESP, 0);
2050         x86_mov_reg_membase (code, dreg, X86_ESP, 0, 2);
2051         x86_alu_reg_imm (code, X86_OR, dreg, 0xc00);
2052         x86_mov_membase_reg (code, X86_ESP, 2, dreg, 2);
2053         x86_fldcw_membase (code, X86_ESP, 2);
2054         if (size == 8) {
2055                 x86_alu_reg_imm (code, X86_SUB, X86_ESP, 8);
2056                 x86_fist_pop_membase (code, X86_ESP, 0, TRUE);
2057                 x86_pop_reg (code, dreg);
2058                 /* FIXME: need the high register 
2059                  * x86_pop_reg (code, dreg_high);
2060                  */
2061         } else {
2062                 x86_push_reg (code, X86_EAX); // SP = SP - 4
2063                 x86_fist_pop_membase (code, X86_ESP, 0, FALSE);
2064                 x86_pop_reg (code, dreg);
2065         }
2066         x86_fldcw_membase (code, X86_ESP, 0);
2067         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
2068
2069         if (size == 1)
2070                 x86_widen_reg (code, dreg, dreg, is_signed, FALSE);
2071         else if (size == 2)
2072                 x86_widen_reg (code, dreg, dreg, is_signed, TRUE);
2073         return code;
2074 }
2075
2076 static unsigned char*
2077 mono_emit_stack_alloc (guchar *code, MonoInst* tree)
2078 {
2079         int sreg = tree->sreg1;
2080         int need_touch = FALSE;
2081
2082 #if defined(TARGET_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK)
2083         need_touch = TRUE;
2084 #endif
2085
2086         if (need_touch) {
2087                 guint8* br[5];
2088
2089                 /*
2090                  * Under Windows:
2091                  * If requested stack size is larger than one page,
2092                  * perform stack-touch operation
2093                  */
2094                 /*
2095                  * Generate stack probe code.
2096                  * Under Windows, it is necessary to allocate one page at a time,
2097                  * "touching" stack after each successful sub-allocation. This is
2098                  * because of the way stack growth is implemented - there is a
2099                  * guard page before the lowest stack page that is currently commited.
2100                  * Stack normally grows sequentially so OS traps access to the
2101                  * guard page and commits more pages when needed.
2102                  */
2103                 x86_test_reg_imm (code, sreg, ~0xFFF);
2104                 br[0] = code; x86_branch8 (code, X86_CC_Z, 0, FALSE);
2105
2106                 br[2] = code; /* loop */
2107                 x86_alu_reg_imm (code, X86_SUB, X86_ESP, 0x1000);
2108                 x86_test_membase_reg (code, X86_ESP, 0, X86_ESP);
2109
2110                 /* 
2111                  * By the end of the loop, sreg2 is smaller than 0x1000, so the init routine
2112                  * that follows only initializes the last part of the area.
2113                  */
2114                 /* Same as the init code below with size==0x1000 */
2115                 if (tree->flags & MONO_INST_INIT) {
2116                         x86_push_reg (code, X86_EAX);
2117                         x86_push_reg (code, X86_ECX);
2118                         x86_push_reg (code, X86_EDI);
2119                         x86_mov_reg_imm (code, X86_ECX, (0x1000 >> 2));
2120                         x86_alu_reg_reg (code, X86_XOR, X86_EAX, X86_EAX);                              
2121                         x86_lea_membase (code, X86_EDI, X86_ESP, 12);
2122                         x86_cld (code);
2123                         x86_prefix (code, X86_REP_PREFIX);
2124                         x86_stosl (code);
2125                         x86_pop_reg (code, X86_EDI);
2126                         x86_pop_reg (code, X86_ECX);
2127                         x86_pop_reg (code, X86_EAX);
2128                 }
2129
2130                 x86_alu_reg_imm (code, X86_SUB, sreg, 0x1000);
2131                 x86_alu_reg_imm (code, X86_CMP, sreg, 0x1000);
2132                 br[3] = code; x86_branch8 (code, X86_CC_AE, 0, FALSE);
2133                 x86_patch (br[3], br[2]);
2134                 x86_test_reg_reg (code, sreg, sreg);
2135                 br[4] = code; x86_branch8 (code, X86_CC_Z, 0, FALSE);
2136                 x86_alu_reg_reg (code, X86_SUB, X86_ESP, sreg);
2137
2138                 br[1] = code; x86_jump8 (code, 0);
2139
2140                 x86_patch (br[0], code);
2141                 x86_alu_reg_reg (code, X86_SUB, X86_ESP, sreg);
2142                 x86_patch (br[1], code);
2143                 x86_patch (br[4], code);
2144         }
2145         else
2146                 x86_alu_reg_reg (code, X86_SUB, X86_ESP, tree->sreg1);
2147
2148         if (tree->flags & MONO_INST_INIT) {
2149                 int offset = 0;
2150                 if (tree->dreg != X86_EAX && sreg != X86_EAX) {
2151                         x86_push_reg (code, X86_EAX);
2152                         offset += 4;
2153                 }
2154                 if (tree->dreg != X86_ECX && sreg != X86_ECX) {
2155                         x86_push_reg (code, X86_ECX);
2156                         offset += 4;
2157                 }
2158                 if (tree->dreg != X86_EDI && sreg != X86_EDI) {
2159                         x86_push_reg (code, X86_EDI);
2160                         offset += 4;
2161                 }
2162                 
2163                 x86_shift_reg_imm (code, X86_SHR, sreg, 2);
2164                 if (sreg != X86_ECX)
2165                         x86_mov_reg_reg (code, X86_ECX, sreg, 4);
2166                 x86_alu_reg_reg (code, X86_XOR, X86_EAX, X86_EAX);
2167                                 
2168                 x86_lea_membase (code, X86_EDI, X86_ESP, offset);
2169                 x86_cld (code);
2170                 x86_prefix (code, X86_REP_PREFIX);
2171                 x86_stosl (code);
2172                 
2173                 if (tree->dreg != X86_EDI && sreg != X86_EDI)
2174                         x86_pop_reg (code, X86_EDI);
2175                 if (tree->dreg != X86_ECX && sreg != X86_ECX)
2176                         x86_pop_reg (code, X86_ECX);
2177                 if (tree->dreg != X86_EAX && sreg != X86_EAX)
2178                         x86_pop_reg (code, X86_EAX);
2179         }
2180         return code;
2181 }
2182
2183
2184 static guint8*
2185 emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code)
2186 {
2187         /* Move return value to the target register */
2188         switch (ins->opcode) {
2189         case OP_CALL:
2190         case OP_CALL_REG:
2191         case OP_CALL_MEMBASE:
2192                 if (ins->dreg != X86_EAX)
2193                         x86_mov_reg_reg (code, ins->dreg, X86_EAX, 4);
2194                 break;
2195         default:
2196                 break;
2197         }
2198
2199         return code;
2200 }
2201
2202 #ifdef __APPLE__
2203 static int tls_gs_offset;
2204 #endif
2205
2206 gboolean
2207 mono_x86_have_tls_get (void)
2208 {
2209 #ifdef __APPLE__
2210         static gboolean have_tls_get = FALSE;
2211         static gboolean inited = FALSE;
2212
2213         if (inited)
2214                 return have_tls_get;
2215
2216         guint32 *ins = (guint32*)pthread_getspecific;
2217         /*
2218          * We're looking for these two instructions:
2219          *
2220          * mov    0x4(%esp),%eax
2221          * mov    %gs:[offset](,%eax,4),%eax
2222          */
2223         have_tls_get = ins [0] == 0x0424448b && ins [1] == 0x85048b65;
2224         tls_gs_offset = ins [2];
2225
2226         inited = TRUE;
2227
2228         return have_tls_get;
2229 #else
2230         return TRUE;
2231 #endif
2232 }
2233
2234 /*
2235  * mono_x86_emit_tls_get:
2236  * @code: buffer to store code to
2237  * @dreg: hard register where to place the result
2238  * @tls_offset: offset info
2239  *
2240  * mono_x86_emit_tls_get emits in @code the native code that puts in
2241  * the dreg register the item in the thread local storage identified
2242  * by tls_offset.
2243  *
2244  * Returns: a pointer to the end of the stored code
2245  */
2246 guint8*
2247 mono_x86_emit_tls_get (guint8* code, int dreg, int tls_offset)
2248 {
2249 #if defined(__APPLE__)
2250         x86_prefix (code, X86_GS_PREFIX);
2251         x86_mov_reg_mem (code, dreg, tls_gs_offset + (tls_offset * 4), 4);
2252 #elif defined(TARGET_WIN32)
2253         /* 
2254          * See the Under the Hood article in the May 1996 issue of Microsoft Systems 
2255          * Journal and/or a disassembly of the TlsGet () function.
2256          */
2257         g_assert (tls_offset < 64);
2258         x86_prefix (code, X86_FS_PREFIX);
2259         x86_mov_reg_mem (code, dreg, 0x18, 4);
2260         /* Dunno what this does but TlsGetValue () contains it */
2261         x86_alu_membase_imm (code, X86_AND, dreg, 0x34, 0);
2262         x86_mov_reg_membase (code, dreg, dreg, 3600 + (tls_offset * 4), 4);
2263 #else
2264         if (optimize_for_xen) {
2265                 x86_prefix (code, X86_GS_PREFIX);
2266                 x86_mov_reg_mem (code, dreg, 0, 4);
2267                 x86_mov_reg_membase (code, dreg, dreg, tls_offset, 4);
2268         } else {
2269                 x86_prefix (code, X86_GS_PREFIX);
2270                 x86_mov_reg_mem (code, dreg, tls_offset, 4);
2271         }
2272 #endif
2273         return code;
2274 }
2275
2276 /*
2277  * emit_load_volatile_arguments:
2278  *
2279  *  Load volatile arguments from the stack to the original input registers.
2280  * Required before a tail call.
2281  */
2282 static guint8*
2283 emit_load_volatile_arguments (MonoCompile *cfg, guint8 *code)
2284 {
2285         MonoMethod *method = cfg->method;
2286         MonoMethodSignature *sig;
2287         MonoInst *inst;
2288         CallInfo *cinfo;
2289         guint32 i;
2290
2291         /* FIXME: Generate intermediate code instead */
2292
2293         sig = mono_method_signature (method);
2294
2295         cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
2296         
2297         /* This is the opposite of the code in emit_prolog */
2298
2299         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
2300                 ArgInfo *ainfo = cinfo->args + i;
2301                 MonoType *arg_type;
2302                 inst = cfg->args [i];
2303
2304                 if (sig->hasthis && (i == 0))
2305                         arg_type = &mono_defaults.object_class->byval_arg;
2306                 else
2307                         arg_type = sig->params [i - sig->hasthis];
2308
2309                 /*
2310                  * On x86, the arguments are either in their original stack locations, or in
2311                  * global regs.
2312                  */
2313                 if (inst->opcode == OP_REGVAR) {
2314                         g_assert (ainfo->storage == ArgOnStack);
2315                         
2316                         x86_mov_membase_reg (code, X86_EBP, inst->inst_offset, inst->dreg, 4);
2317                 }
2318         }
2319
2320         return code;
2321 }
2322
2323 #define REAL_PRINT_REG(text,reg) \
2324 mono_assert (reg >= 0); \
2325 x86_push_reg (code, X86_EAX); \
2326 x86_push_reg (code, X86_EDX); \
2327 x86_push_reg (code, X86_ECX); \
2328 x86_push_reg (code, reg); \
2329 x86_push_imm (code, reg); \
2330 x86_push_imm (code, text " %d %p\n"); \
2331 x86_mov_reg_imm (code, X86_EAX, printf); \
2332 x86_call_reg (code, X86_EAX); \
2333 x86_alu_reg_imm (code, X86_ADD, X86_ESP, 3*4); \
2334 x86_pop_reg (code, X86_ECX); \
2335 x86_pop_reg (code, X86_EDX); \
2336 x86_pop_reg (code, X86_EAX);
2337
2338 /* REAL_PRINT_REG does not appear to be used, and was not adapted to work with Native Client. */
2339 #ifdef __native__client_codegen__
2340 #define REAL_PRINT_REG(text, reg) g_assert_not_reached()
2341 #endif
2342
2343 /* benchmark and set based on cpu */
2344 #define LOOP_ALIGNMENT 8
2345 #define bb_is_loop_start(bb) ((bb)->loop_body_start && (bb)->nesting)
2346
2347 #ifndef DISABLE_JIT
2348
2349 #if defined(__native_client__) || defined(__native_client_codegen__)
2350 void
2351 mono_nacl_gc()
2352 {
2353 #ifdef __native_client_gc__
2354         __nacl_suspend_thread_if_needed();
2355 #endif
2356 }
2357 #endif
2358
2359 void
2360 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2361 {
2362         MonoInst *ins;
2363         MonoCallInst *call;
2364         guint offset;
2365         guint8 *code = cfg->native_code + cfg->code_len;
2366         int max_len, cpos;
2367
2368         if (cfg->opt & MONO_OPT_LOOP) {
2369                 int pad, align = LOOP_ALIGNMENT;
2370                 /* set alignment depending on cpu */
2371                 if (bb_is_loop_start (bb) && (pad = (cfg->code_len & (align - 1)))) {
2372                         pad = align - pad;
2373                         /*g_print ("adding %d pad at %x to loop in %s\n", pad, cfg->code_len, cfg->method->name);*/
2374                         x86_padding (code, pad);
2375                         cfg->code_len += pad;
2376                         bb->native_offset = cfg->code_len;
2377                 }
2378         }
2379 #ifdef __native_client_codegen__
2380         {
2381                 /* For Native Client, all indirect call/jump targets must be   */
2382                 /* 32-byte aligned.  Exception handler blocks are jumped to    */
2383                 /* indirectly as well.                                         */
2384                 gboolean bb_needs_alignment = (bb->flags & BB_INDIRECT_JUMP_TARGET) ||
2385                         (bb->flags & BB_EXCEPTION_HANDLER);
2386
2387                 /* if ((cfg->code_len & kNaClAlignmentMask) != 0) { */
2388                 if ( bb_needs_alignment && ((cfg->code_len & kNaClAlignmentMask) != 0)) {
2389             int pad = kNaClAlignment - (cfg->code_len & kNaClAlignmentMask);
2390             if (pad != kNaClAlignment) code = mono_arch_nacl_pad(code, pad);
2391             cfg->code_len += pad;
2392             bb->native_offset = cfg->code_len;
2393                 }
2394         }
2395 #endif  /* __native_client_codegen__ */
2396         if (cfg->verbose_level > 2)
2397                 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2398
2399         cpos = bb->max_offset;
2400
2401         if (cfg->prof_options & MONO_PROFILE_COVERAGE) {
2402                 MonoProfileCoverageInfo *cov = cfg->coverage_info;
2403                 g_assert (!cfg->compile_aot);
2404                 cpos += 6;
2405
2406                 cov->data [bb->dfn].cil_code = bb->cil_code;
2407                 /* this is not thread save, but good enough */
2408                 x86_inc_mem (code, &cov->data [bb->dfn].count); 
2409         }
2410
2411         offset = code - cfg->native_code;
2412
2413         mono_debug_open_block (cfg, bb, offset);
2414
2415     if (mono_break_at_bb_method && mono_method_desc_full_match (mono_break_at_bb_method, cfg->method) && bb->block_num == mono_break_at_bb_bb_num)
2416                 x86_breakpoint (code);
2417
2418         MONO_BB_FOR_EACH_INS (bb, ins) {
2419                 offset = code - cfg->native_code;
2420
2421                 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
2422
2423 #define EXTRA_CODE_SPACE (NACL_SIZE (16, 16 + kNaClAlignment))
2424
2425                 if (G_UNLIKELY (offset > (cfg->code_size - max_len - EXTRA_CODE_SPACE))) {
2426                         cfg->code_size *= 2;
2427                         cfg->native_code = mono_realloc_native_code(cfg);
2428                         code = cfg->native_code + offset;
2429                         mono_jit_stats.code_reallocs++;
2430                 }
2431
2432                 if (cfg->debug_info)
2433                         mono_debug_record_line_number (cfg, ins, offset);
2434
2435                 switch (ins->opcode) {
2436                 case OP_BIGMUL:
2437                         x86_mul_reg (code, ins->sreg2, TRUE);
2438                         break;
2439                 case OP_BIGMUL_UN:
2440                         x86_mul_reg (code, ins->sreg2, FALSE);
2441                         break;
2442                 case OP_X86_SETEQ_MEMBASE:
2443                 case OP_X86_SETNE_MEMBASE:
2444                         x86_set_membase (code, ins->opcode == OP_X86_SETEQ_MEMBASE ? X86_CC_EQ : X86_CC_NE,
2445                                          ins->inst_basereg, ins->inst_offset, TRUE);
2446                         break;
2447                 case OP_STOREI1_MEMBASE_IMM:
2448                         x86_mov_membase_imm (code, ins->inst_destbasereg, ins->inst_offset, ins->inst_imm, 1);
2449                         break;
2450                 case OP_STOREI2_MEMBASE_IMM:
2451                         x86_mov_membase_imm (code, ins->inst_destbasereg, ins->inst_offset, ins->inst_imm, 2);
2452                         break;
2453                 case OP_STORE_MEMBASE_IMM:
2454                 case OP_STOREI4_MEMBASE_IMM:
2455                         x86_mov_membase_imm (code, ins->inst_destbasereg, ins->inst_offset, ins->inst_imm, 4);
2456                         break;
2457                 case OP_STOREI1_MEMBASE_REG:
2458                         x86_mov_membase_reg (code, ins->inst_destbasereg, ins->inst_offset, ins->sreg1, 1);
2459                         break;
2460                 case OP_STOREI2_MEMBASE_REG:
2461                         x86_mov_membase_reg (code, ins->inst_destbasereg, ins->inst_offset, ins->sreg1, 2);
2462                         break;
2463                 case OP_STORE_MEMBASE_REG:
2464                 case OP_STOREI4_MEMBASE_REG:
2465                         x86_mov_membase_reg (code, ins->inst_destbasereg, ins->inst_offset, ins->sreg1, 4);
2466                         break;
2467                 case OP_STORE_MEM_IMM:
2468                         x86_mov_mem_imm (code, ins->inst_p0, ins->inst_c0, 4);
2469                         break;
2470                 case OP_LOADU4_MEM:
2471                         x86_mov_reg_mem (code, ins->dreg, ins->inst_imm, 4);
2472                         break;
2473                 case OP_LOAD_MEM:
2474                 case OP_LOADI4_MEM:
2475                         /* These are created by the cprop pass so they use inst_imm as the source */
2476                         x86_mov_reg_mem (code, ins->dreg, ins->inst_imm, 4);
2477                         break;
2478                 case OP_LOADU1_MEM:
2479                         x86_widen_mem (code, ins->dreg, ins->inst_imm, FALSE, FALSE);
2480                         break;
2481                 case OP_LOADU2_MEM:
2482                         x86_widen_mem (code, ins->dreg, ins->inst_imm, FALSE, TRUE);
2483                         break;
2484                 case OP_LOAD_MEMBASE:
2485                 case OP_LOADI4_MEMBASE:
2486                 case OP_LOADU4_MEMBASE:
2487                         x86_mov_reg_membase (code, ins->dreg, ins->inst_basereg, ins->inst_offset, 4);
2488                         break;
2489                 case OP_LOADU1_MEMBASE:
2490                         x86_widen_membase (code, ins->dreg, ins->inst_basereg, ins->inst_offset, FALSE, FALSE);
2491                         break;
2492                 case OP_LOADI1_MEMBASE:
2493                         x86_widen_membase (code, ins->dreg, ins->inst_basereg, ins->inst_offset, TRUE, FALSE);
2494                         break;
2495                 case OP_LOADU2_MEMBASE:
2496                         x86_widen_membase (code, ins->dreg, ins->inst_basereg, ins->inst_offset, FALSE, TRUE);
2497                         break;
2498                 case OP_LOADI2_MEMBASE:
2499                         x86_widen_membase (code, ins->dreg, ins->inst_basereg, ins->inst_offset, TRUE, TRUE);
2500                         break;
2501                 case OP_ICONV_TO_I1:
2502                 case OP_SEXT_I1:
2503                         x86_widen_reg (code, ins->dreg, ins->sreg1, TRUE, FALSE);
2504                         break;
2505                 case OP_ICONV_TO_I2:
2506                 case OP_SEXT_I2:
2507                         x86_widen_reg (code, ins->dreg, ins->sreg1, TRUE, TRUE);
2508                         break;
2509                 case OP_ICONV_TO_U1:
2510                         x86_widen_reg (code, ins->dreg, ins->sreg1, FALSE, FALSE);
2511                         break;
2512                 case OP_ICONV_TO_U2:
2513                         x86_widen_reg (code, ins->dreg, ins->sreg1, FALSE, TRUE);
2514                         break;
2515                 case OP_COMPARE:
2516                 case OP_ICOMPARE:
2517                         x86_alu_reg_reg (code, X86_CMP, ins->sreg1, ins->sreg2);
2518                         break;
2519                 case OP_COMPARE_IMM:
2520                 case OP_ICOMPARE_IMM:
2521                         x86_alu_reg_imm (code, X86_CMP, ins->sreg1, ins->inst_imm);
2522                         break;
2523                 case OP_X86_COMPARE_MEMBASE_REG:
2524                         x86_alu_membase_reg (code, X86_CMP, ins->inst_basereg, ins->inst_offset, ins->sreg2);
2525                         break;
2526                 case OP_X86_COMPARE_MEMBASE_IMM:
2527                         x86_alu_membase_imm (code, X86_CMP, ins->inst_basereg, ins->inst_offset, ins->inst_imm);
2528                         break;
2529                 case OP_X86_COMPARE_MEMBASE8_IMM:
2530                         x86_alu_membase8_imm (code, X86_CMP, ins->inst_basereg, ins->inst_offset, ins->inst_imm);
2531                         break;
2532                 case OP_X86_COMPARE_REG_MEMBASE:
2533                         x86_alu_reg_membase (code, X86_CMP, ins->sreg1, ins->sreg2, ins->inst_offset);
2534                         break;
2535                 case OP_X86_COMPARE_MEM_IMM:
2536                         x86_alu_mem_imm (code, X86_CMP, ins->inst_offset, ins->inst_imm);
2537                         break;
2538                 case OP_X86_TEST_NULL:
2539                         x86_test_reg_reg (code, ins->sreg1, ins->sreg1);
2540                         break;
2541                 case OP_X86_ADD_MEMBASE_IMM:
2542                         x86_alu_membase_imm (code, X86_ADD, ins->inst_basereg, ins->inst_offset, ins->inst_imm);
2543                         break;
2544                 case OP_X86_ADD_REG_MEMBASE:
2545                         x86_alu_reg_membase (code, X86_ADD, ins->sreg1, ins->sreg2, ins->inst_offset);
2546                         break;
2547                 case OP_X86_SUB_MEMBASE_IMM:
2548                         x86_alu_membase_imm (code, X86_SUB, ins->inst_basereg, ins->inst_offset, ins->inst_imm);
2549                         break;
2550                 case OP_X86_SUB_REG_MEMBASE:
2551                         x86_alu_reg_membase (code, X86_SUB, ins->sreg1, ins->sreg2, ins->inst_offset);
2552                         break;
2553                 case OP_X86_AND_MEMBASE_IMM:
2554                         x86_alu_membase_imm (code, X86_AND, ins->inst_basereg, ins->inst_offset, ins->inst_imm);
2555                         break;
2556                 case OP_X86_OR_MEMBASE_IMM:
2557                         x86_alu_membase_imm (code, X86_OR, ins->inst_basereg, ins->inst_offset, ins->inst_imm);
2558                         break;
2559                 case OP_X86_XOR_MEMBASE_IMM:
2560                         x86_alu_membase_imm (code, X86_XOR, ins->inst_basereg, ins->inst_offset, ins->inst_imm);
2561                         break;
2562                 case OP_X86_ADD_MEMBASE_REG:
2563                         x86_alu_membase_reg (code, X86_ADD, ins->inst_basereg, ins->inst_offset, ins->sreg2);
2564                         break;
2565                 case OP_X86_SUB_MEMBASE_REG:
2566                         x86_alu_membase_reg (code, X86_SUB, ins->inst_basereg, ins->inst_offset, ins->sreg2);
2567                         break;
2568                 case OP_X86_AND_MEMBASE_REG:
2569                         x86_alu_membase_reg (code, X86_AND, ins->inst_basereg, ins->inst_offset, ins->sreg2);
2570                         break;
2571                 case OP_X86_OR_MEMBASE_REG:
2572                         x86_alu_membase_reg (code, X86_OR, ins->inst_basereg, ins->inst_offset, ins->sreg2);
2573                         break;
2574                 case OP_X86_XOR_MEMBASE_REG:
2575                         x86_alu_membase_reg (code, X86_XOR, ins->inst_basereg, ins->inst_offset, ins->sreg2);
2576                         break;
2577                 case OP_X86_INC_MEMBASE:
2578                         x86_inc_membase (code, ins->inst_basereg, ins->inst_offset);
2579                         break;
2580                 case OP_X86_INC_REG:
2581                         x86_inc_reg (code, ins->dreg);
2582                         break;
2583                 case OP_X86_DEC_MEMBASE:
2584                         x86_dec_membase (code, ins->inst_basereg, ins->inst_offset);
2585                         break;
2586                 case OP_X86_DEC_REG:
2587                         x86_dec_reg (code, ins->dreg);
2588                         break;
2589                 case OP_X86_MUL_REG_MEMBASE:
2590                         x86_imul_reg_membase (code, ins->sreg1, ins->sreg2, ins->inst_offset);
2591                         break;
2592                 case OP_X86_AND_REG_MEMBASE:
2593                         x86_alu_reg_membase (code, X86_AND, ins->sreg1, ins->sreg2, ins->inst_offset);
2594                         break;
2595                 case OP_X86_OR_REG_MEMBASE:
2596                         x86_alu_reg_membase (code, X86_OR, ins->sreg1, ins->sreg2, ins->inst_offset);
2597                         break;
2598                 case OP_X86_XOR_REG_MEMBASE:
2599                         x86_alu_reg_membase (code, X86_XOR, ins->sreg1, ins->sreg2, ins->inst_offset);
2600                         break;
2601                 case OP_BREAK:
2602                         x86_breakpoint (code);
2603                         break;
2604                 case OP_RELAXED_NOP:
2605                         x86_prefix (code, X86_REP_PREFIX);
2606                         x86_nop (code);
2607                         break;
2608                 case OP_HARD_NOP:
2609                         x86_nop (code);
2610                         break;
2611                 case OP_NOP:
2612                 case OP_DUMMY_USE:
2613                 case OP_DUMMY_STORE:
2614                 case OP_NOT_REACHED:
2615                 case OP_NOT_NULL:
2616                         break;
2617                 case OP_SEQ_POINT: {
2618                         int i;
2619
2620                         if (cfg->compile_aot)
2621                                 NOT_IMPLEMENTED;
2622
2623                         /* 
2624                          * Read from the single stepping trigger page. This will cause a
2625                          * SIGSEGV when single stepping is enabled.
2626                          * We do this _before_ the breakpoint, so single stepping after
2627                          * a breakpoint is hit will step to the next IL offset.
2628                          */
2629                         if (ins->flags & MONO_INST_SINGLE_STEP_LOC)
2630                                 x86_alu_reg_mem (code, X86_CMP, X86_EAX, (guint32)ss_trigger_page);
2631
2632                         mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
2633
2634                         /* 
2635                          * A placeholder for a possible breakpoint inserted by
2636                          * mono_arch_set_breakpoint ().
2637                          */
2638                         for (i = 0; i < 6; ++i)
2639                                 x86_nop (code);
2640                         break;
2641                 }
2642                 case OP_ADDCC:
2643                 case OP_IADDCC:
2644                 case OP_IADD:
2645                         x86_alu_reg_reg (code, X86_ADD, ins->sreg1, ins->sreg2);
2646                         break;
2647                 case OP_ADC:
2648                 case OP_IADC:
2649                         x86_alu_reg_reg (code, X86_ADC, ins->sreg1, ins->sreg2);
2650                         break;
2651                 case OP_ADDCC_IMM:
2652                 case OP_ADD_IMM:
2653                 case OP_IADD_IMM:
2654                         x86_alu_reg_imm (code, X86_ADD, ins->dreg, ins->inst_imm);
2655                         break;
2656                 case OP_ADC_IMM:
2657                 case OP_IADC_IMM:
2658                         x86_alu_reg_imm (code, X86_ADC, ins->dreg, ins->inst_imm);
2659                         break;
2660                 case OP_SUBCC:
2661                 case OP_ISUBCC:
2662                 case OP_ISUB:
2663                         x86_alu_reg_reg (code, X86_SUB, ins->sreg1, ins->sreg2);
2664                         break;
2665                 case OP_SBB:
2666                 case OP_ISBB:
2667                         x86_alu_reg_reg (code, X86_SBB, ins->sreg1, ins->sreg2);
2668                         break;
2669                 case OP_SUBCC_IMM:
2670                 case OP_SUB_IMM:
2671                 case OP_ISUB_IMM:
2672                         x86_alu_reg_imm (code, X86_SUB, ins->dreg, ins->inst_imm);
2673                         break;
2674                 case OP_SBB_IMM:
2675                 case OP_ISBB_IMM:
2676                         x86_alu_reg_imm (code, X86_SBB, ins->dreg, ins->inst_imm);
2677                         break;
2678                 case OP_IAND:
2679                         x86_alu_reg_reg (code, X86_AND, ins->sreg1, ins->sreg2);
2680                         break;
2681                 case OP_AND_IMM:
2682                 case OP_IAND_IMM:
2683                         x86_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_imm);
2684                         break;
2685                 case OP_IDIV:
2686                 case OP_IREM:
2687                         /* 
2688                          * The code is the same for div/rem, the allocator will allocate dreg
2689                          * to RAX/RDX as appropriate.
2690                          */
2691                         if (ins->sreg2 == X86_EDX) {
2692                                 /* cdq clobbers this */
2693                                 x86_push_reg (code, ins->sreg2);
2694                                 x86_cdq (code);
2695                                 x86_div_membase (code, X86_ESP, 0, TRUE);
2696                                 x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);                            
2697                         } else {
2698                                 x86_cdq (code);
2699                                 x86_div_reg (code, ins->sreg2, TRUE);
2700                         }
2701                         break;
2702                 case OP_IDIV_UN:
2703                 case OP_IREM_UN:
2704                         if (ins->sreg2 == X86_EDX) {
2705                                 x86_push_reg (code, ins->sreg2);
2706                                 x86_alu_reg_reg (code, X86_XOR, X86_EDX, X86_EDX);
2707                                 x86_div_membase (code, X86_ESP, 0, FALSE);
2708                                 x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);                            
2709                         } else {
2710                                 x86_alu_reg_reg (code, X86_XOR, X86_EDX, X86_EDX);
2711                                 x86_div_reg (code, ins->sreg2, FALSE);
2712                         }
2713                         break;
2714                 case OP_DIV_IMM:
2715                         x86_mov_reg_imm (code, ins->sreg2, ins->inst_imm);
2716                         x86_cdq (code);
2717                         x86_div_reg (code, ins->sreg2, TRUE);
2718                         break;
2719                 case OP_IREM_IMM: {
2720                         int power = mono_is_power_of_two (ins->inst_imm);
2721
2722                         g_assert (ins->sreg1 == X86_EAX);
2723                         g_assert (ins->dreg == X86_EAX);
2724                         g_assert (power >= 0);
2725
2726                         if (power == 1) {
2727                                 /* Based on http://compilers.iecc.com/comparch/article/93-04-079 */
2728                                 x86_cdq (code);
2729                                 x86_alu_reg_imm (code, X86_AND, X86_EAX, 1);
2730                                 /* 
2731                                  * If the divident is >= 0, this does not nothing. If it is positive, it
2732                                  * it transforms %eax=0 into %eax=0, and %eax=1 into %eax=-1.
2733                                  */
2734                                 x86_alu_reg_reg (code, X86_XOR, X86_EAX, X86_EDX);
2735                                 x86_alu_reg_reg (code, X86_SUB, X86_EAX, X86_EDX);
2736                         } else if (power == 0) {
2737                                 x86_alu_reg_reg (code, X86_XOR, ins->dreg, ins->dreg);
2738                         } else {
2739                                 /* Based on gcc code */
2740
2741                                 /* Add compensation for negative dividents */
2742                                 x86_cdq (code);
2743                                 x86_shift_reg_imm (code, X86_SHR, X86_EDX, 32 - power);
2744                                 x86_alu_reg_reg (code, X86_ADD, X86_EAX, X86_EDX);
2745                                 /* Compute remainder */
2746                                 x86_alu_reg_imm (code, X86_AND, X86_EAX, (1 << power) - 1);
2747                                 /* Remove compensation */
2748                                 x86_alu_reg_reg (code, X86_SUB, X86_EAX, X86_EDX);
2749                         }
2750                         break;
2751                 }
2752                 case OP_IOR:
2753                         x86_alu_reg_reg (code, X86_OR, ins->sreg1, ins->sreg2);
2754                         break;
2755                 case OP_OR_IMM:
2756                 case OP_IOR_IMM:
2757                         x86_alu_reg_imm (code, X86_OR, ins->sreg1, ins->inst_imm);
2758                         break;
2759                 case OP_IXOR:
2760                         x86_alu_reg_reg (code, X86_XOR, ins->sreg1, ins->sreg2);
2761                         break;
2762                 case OP_XOR_IMM:
2763                 case OP_IXOR_IMM:
2764                         x86_alu_reg_imm (code, X86_XOR, ins->sreg1, ins->inst_imm);
2765                         break;
2766                 case OP_ISHL:
2767                         g_assert (ins->sreg2 == X86_ECX);
2768                         x86_shift_reg (code, X86_SHL, ins->dreg);
2769                         break;
2770                 case OP_ISHR:
2771                         g_assert (ins->sreg2 == X86_ECX);
2772                         x86_shift_reg (code, X86_SAR, ins->dreg);
2773                         break;
2774                 case OP_SHR_IMM:
2775                 case OP_ISHR_IMM:
2776                         x86_shift_reg_imm (code, X86_SAR, ins->dreg, ins->inst_imm);
2777                         break;
2778                 case OP_SHR_UN_IMM:
2779                 case OP_ISHR_UN_IMM:
2780                         x86_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_imm);
2781                         break;
2782                 case OP_ISHR_UN:
2783                         g_assert (ins->sreg2 == X86_ECX);
2784                         x86_shift_reg (code, X86_SHR, ins->dreg);
2785                         break;
2786                 case OP_SHL_IMM:
2787                 case OP_ISHL_IMM:
2788                         x86_shift_reg_imm (code, X86_SHL, ins->dreg, ins->inst_imm);
2789                         break;
2790                 case OP_LSHL: {
2791                         guint8 *jump_to_end;
2792
2793                         /* handle shifts below 32 bits */
2794                         x86_shld_reg (code, ins->backend.reg3, ins->sreg1);
2795                         x86_shift_reg (code, X86_SHL, ins->sreg1);
2796
2797                         x86_test_reg_imm (code, X86_ECX, 32);
2798                         jump_to_end = code; x86_branch8 (code, X86_CC_EQ, 0, TRUE);
2799
2800                         /* handle shift over 32 bit */
2801                         x86_mov_reg_reg (code, ins->backend.reg3, ins->sreg1, 4);
2802                         x86_clear_reg (code, ins->sreg1);
2803                         
2804                         x86_patch (jump_to_end, code);
2805                         }
2806                         break;
2807                 case OP_LSHR: {
2808                         guint8 *jump_to_end;
2809
2810                         /* handle shifts below 32 bits */
2811                         x86_shrd_reg (code, ins->sreg1, ins->backend.reg3);
2812                         x86_shift_reg (code, X86_SAR, ins->backend.reg3);
2813
2814                         x86_test_reg_imm (code, X86_ECX, 32);
2815                         jump_to_end = code; x86_branch8 (code, X86_CC_EQ, 0, FALSE);
2816
2817                         /* handle shifts over 31 bits */
2818                         x86_mov_reg_reg (code, ins->sreg1, ins->backend.reg3, 4);
2819                         x86_shift_reg_imm (code, X86_SAR, ins->backend.reg3, 31);
2820                         
2821                         x86_patch (jump_to_end, code);
2822                         }
2823                         break;
2824                 case OP_LSHR_UN: {
2825                         guint8 *jump_to_end;
2826
2827                         /* handle shifts below 32 bits */
2828                         x86_shrd_reg (code, ins->sreg1, ins->backend.reg3);
2829                         x86_shift_reg (code, X86_SHR, ins->backend.reg3);
2830
2831                         x86_test_reg_imm (code, X86_ECX, 32);
2832                         jump_to_end = code; x86_branch8 (code, X86_CC_EQ, 0, FALSE);
2833
2834                         /* handle shifts over 31 bits */
2835                         x86_mov_reg_reg (code, ins->sreg1, ins->backend.reg3, 4);
2836                         x86_clear_reg (code, ins->backend.reg3);
2837                         
2838                         x86_patch (jump_to_end, code);
2839                         }
2840                         break;
2841                 case OP_LSHL_IMM:
2842                         if (ins->inst_imm >= 32) {
2843                                 x86_mov_reg_reg (code, ins->backend.reg3, ins->sreg1, 4);
2844                                 x86_clear_reg (code, ins->sreg1);
2845                                 x86_shift_reg_imm (code, X86_SHL, ins->backend.reg3, ins->inst_imm - 32);
2846                         } else {
2847                                 x86_shld_reg_imm (code, ins->backend.reg3, ins->sreg1, ins->inst_imm);
2848                                 x86_shift_reg_imm (code, X86_SHL, ins->sreg1, ins->inst_imm);
2849                         }
2850                         break;
2851                 case OP_LSHR_IMM:
2852                         if (ins->inst_imm >= 32) {
2853                                 x86_mov_reg_reg (code, ins->sreg1, ins->backend.reg3,  4);
2854                                 x86_shift_reg_imm (code, X86_SAR, ins->backend.reg3, 0x1f);
2855                                 x86_shift_reg_imm (code, X86_SAR, ins->sreg1, ins->inst_imm - 32);
2856                         } else {
2857                                 x86_shrd_reg_imm (code, ins->sreg1, ins->backend.reg3, ins->inst_imm);
2858                                 x86_shift_reg_imm (code, X86_SAR, ins->backend.reg3, ins->inst_imm);
2859                         }
2860                         break;
2861                 case OP_LSHR_UN_IMM:
2862                         if (ins->inst_imm >= 32) {
2863                                 x86_mov_reg_reg (code, ins->sreg1, ins->backend.reg3, 4);
2864                                 x86_clear_reg (code, ins->backend.reg3);
2865                                 x86_shift_reg_imm (code, X86_SHR, ins->sreg1, ins->inst_imm - 32);
2866                         } else {
2867                                 x86_shrd_reg_imm (code, ins->sreg1, ins->backend.reg3, ins->inst_imm);
2868                                 x86_shift_reg_imm (code, X86_SHR, ins->backend.reg3, ins->inst_imm);
2869                         }
2870                         break;
2871                 case OP_INOT:
2872                         x86_not_reg (code, ins->sreg1);
2873                         break;
2874                 case OP_INEG:
2875                         x86_neg_reg (code, ins->sreg1);
2876                         break;
2877
2878                 case OP_IMUL:
2879                         x86_imul_reg_reg (code, ins->sreg1, ins->sreg2);
2880                         break;
2881                 case OP_MUL_IMM:
2882                 case OP_IMUL_IMM:
2883                         switch (ins->inst_imm) {
2884                         case 2:
2885                                 /* MOV r1, r2 */
2886                                 /* ADD r1, r1 */
2887                                 if (ins->dreg != ins->sreg1)
2888                                         x86_mov_reg_reg (code, ins->dreg, ins->sreg1, 4);
2889                                 x86_alu_reg_reg (code, X86_ADD, ins->dreg, ins->dreg);
2890                                 break;
2891                         case 3:
2892                                 /* LEA r1, [r2 + r2*2] */
2893                                 x86_lea_memindex (code, ins->dreg, ins->sreg1, 0, ins->sreg1, 1);
2894                                 break;
2895                         case 5:
2896                                 /* LEA r1, [r2 + r2*4] */
2897                                 x86_lea_memindex (code, ins->dreg, ins->sreg1, 0, ins->sreg1, 2);
2898                                 break;
2899                         case 6:
2900                                 /* LEA r1, [r2 + r2*2] */
2901                                 /* ADD r1, r1          */
2902                                 x86_lea_memindex (code, ins->dreg, ins->sreg1, 0, ins->sreg1, 1);
2903                                 x86_alu_reg_reg (code, X86_ADD, ins->dreg, ins->dreg);
2904                                 break;
2905                         case 9:
2906                                 /* LEA r1, [r2 + r2*8] */
2907                                 x86_lea_memindex (code, ins->dreg, ins->sreg1, 0, ins->sreg1, 3);
2908                                 break;
2909                         case 10:
2910                                 /* LEA r1, [r2 + r2*4] */
2911                                 /* ADD r1, r1          */
2912                                 x86_lea_memindex (code, ins->dreg, ins->sreg1, 0, ins->sreg1, 2);
2913                                 x86_alu_reg_reg (code, X86_ADD, ins->dreg, ins->dreg);
2914                                 break;
2915                         case 12:
2916                                 /* LEA r1, [r2 + r2*2] */
2917                                 /* SHL r1, 2           */
2918                                 x86_lea_memindex (code, ins->dreg, ins->sreg1, 0, ins->sreg1, 1);
2919                                 x86_shift_reg_imm (code, X86_SHL, ins->dreg, 2);
2920                                 break;
2921                         case 25:
2922                                 /* LEA r1, [r2 + r2*4] */
2923                                 /* LEA r1, [r1 + r1*4] */
2924                                 x86_lea_memindex (code, ins->dreg, ins->sreg1, 0, ins->sreg1, 2);
2925                                 x86_lea_memindex (code, ins->dreg, ins->dreg, 0, ins->dreg, 2);
2926                                 break;
2927                         case 100:
2928                                 /* LEA r1, [r2 + r2*4] */
2929                                 /* SHL r1, 2           */
2930                                 /* LEA r1, [r1 + r1*4] */
2931                                 x86_lea_memindex (code, ins->dreg, ins->sreg1, 0, ins->sreg1, 2);
2932                                 x86_shift_reg_imm (code, X86_SHL, ins->dreg, 2);
2933                                 x86_lea_memindex (code, ins->dreg, ins->dreg, 0, ins->dreg, 2);
2934                                 break;
2935                         default:
2936                                 x86_imul_reg_reg_imm (code, ins->dreg, ins->sreg1, ins->inst_imm);
2937                                 break;
2938                         }
2939                         break;
2940                 case OP_IMUL_OVF:
2941                         x86_imul_reg_reg (code, ins->sreg1, ins->sreg2);
2942                         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_O, FALSE, "OverflowException");
2943                         break;
2944                 case OP_IMUL_OVF_UN: {
2945                         /* the mul operation and the exception check should most likely be split */
2946                         int non_eax_reg, saved_eax = FALSE, saved_edx = FALSE;
2947                         /*g_assert (ins->sreg2 == X86_EAX);
2948                         g_assert (ins->dreg == X86_EAX);*/
2949                         if (ins->sreg2 == X86_EAX) {
2950                                 non_eax_reg = ins->sreg1;
2951                         } else if (ins->sreg1 == X86_EAX) {
2952                                 non_eax_reg = ins->sreg2;
2953                         } else {
2954                                 /* no need to save since we're going to store to it anyway */
2955                                 if (ins->dreg != X86_EAX) {
2956                                         saved_eax = TRUE;
2957                                         x86_push_reg (code, X86_EAX);
2958                                 }
2959                                 x86_mov_reg_reg (code, X86_EAX, ins->sreg1, 4);
2960                                 non_eax_reg = ins->sreg2;
2961                         }
2962                         if (ins->dreg == X86_EDX) {
2963                                 if (!saved_eax) {
2964                                         saved_eax = TRUE;
2965                                         x86_push_reg (code, X86_EAX);
2966                                 }
2967                         } else if (ins->dreg != X86_EAX) {
2968                                 saved_edx = TRUE;
2969                                 x86_push_reg (code, X86_EDX);
2970                         }
2971                         x86_mul_reg (code, non_eax_reg, FALSE);
2972                         /* save before the check since pop and mov don't change the flags */
2973                         if (ins->dreg != X86_EAX)
2974                                 x86_mov_reg_reg (code, ins->dreg, X86_EAX, 4);
2975                         if (saved_edx)
2976                                 x86_pop_reg (code, X86_EDX);
2977                         if (saved_eax)
2978                                 x86_pop_reg (code, X86_EAX);
2979                         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_O, FALSE, "OverflowException");
2980                         break;
2981                 }
2982                 case OP_ICONST:
2983                         x86_mov_reg_imm (code, ins->dreg, ins->inst_c0);
2984                         break;
2985                 case OP_AOTCONST:
2986                         g_assert_not_reached ();
2987                         mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
2988                         x86_mov_reg_imm (code, ins->dreg, 0);
2989                         break;
2990                 case OP_JUMP_TABLE:
2991                         mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
2992                         x86_mov_reg_imm (code, ins->dreg, 0);
2993                         break;
2994                 case OP_LOAD_GOTADDR:
2995                         g_assert (ins->dreg == MONO_ARCH_GOT_REG);
2996                         code = mono_arch_emit_load_got_addr (cfg->native_code, code, cfg, NULL);
2997                         break;
2998                 case OP_GOT_ENTRY:
2999                         mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_right->inst_i1, ins->inst_right->inst_p0);
3000                         x86_mov_reg_membase (code, ins->dreg, ins->inst_basereg, 0xf0f0f0f0, 4);
3001                         break;
3002                 case OP_X86_PUSH_GOT_ENTRY:
3003                         mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_right->inst_i1, ins->inst_right->inst_p0);
3004                         x86_push_membase (code, ins->inst_basereg, 0xf0f0f0f0);
3005                         break;
3006                 case OP_MOVE:
3007                         x86_mov_reg_reg (code, ins->dreg, ins->sreg1, 4);
3008                         break;
3009                 case OP_JMP: {
3010                         /*
3011                          * Note: this 'frame destruction' logic is useful for tail calls, too.
3012                          * Keep in sync with the code in emit_epilog.
3013                          */
3014                         int pos = 0;
3015
3016                         /* FIXME: no tracing support... */
3017                         if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
3018                                 code = mono_arch_instrument_epilog (cfg, mono_profiler_method_leave, code, FALSE);
3019                         /* reset offset to make max_len work */
3020                         offset = code - cfg->native_code;
3021
3022                         g_assert (!cfg->method->save_lmf);
3023
3024                         code = emit_load_volatile_arguments (cfg, code);
3025
3026                         if (cfg->used_int_regs & (1 << X86_EBX))
3027                                 pos -= 4;
3028                         if (cfg->used_int_regs & (1 << X86_EDI))
3029                                 pos -= 4;
3030                         if (cfg->used_int_regs & (1 << X86_ESI))
3031                                 pos -= 4;
3032                         if (pos)
3033                                 x86_lea_membase (code, X86_ESP, X86_EBP, pos);
3034         
3035                         if (cfg->used_int_regs & (1 << X86_ESI))
3036                                 x86_pop_reg (code, X86_ESI);
3037                         if (cfg->used_int_regs & (1 << X86_EDI))
3038                                 x86_pop_reg (code, X86_EDI);
3039                         if (cfg->used_int_regs & (1 << X86_EBX))
3040                                 x86_pop_reg (code, X86_EBX);
3041         
3042                         /* restore ESP/EBP */
3043                         x86_leave (code);
3044                         offset = code - cfg->native_code;
3045                         mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_METHOD_JUMP, ins->inst_p0);
3046                         x86_jump32 (code, 0);
3047
3048                         cfg->disable_aot = TRUE;
3049                         break;
3050                 }
3051                 case OP_TAILCALL: {
3052                         MonoCallInst *call = (MonoCallInst*)ins;
3053                         int pos = 0, i;
3054
3055                         /* FIXME: no tracing support... */
3056                         if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
3057                                 code = mono_arch_instrument_epilog (cfg, mono_profiler_method_leave, code, FALSE);
3058                         /* reset offset to make max_len work */
3059                         offset = code - cfg->native_code;
3060
3061                         g_assert (!cfg->method->save_lmf);
3062
3063                         //code = emit_load_volatile_arguments (cfg, code);
3064
3065                         /* restore callee saved registers */
3066                         for (i = 0; i < X86_NREG; ++i)
3067                                 if (X86_IS_CALLEE_SAVED_REG (i) && cfg->used_int_regs & (1 << i))
3068                                         pos -= 4;
3069                         if (cfg->used_int_regs & (1 << X86_ESI)) {
3070                                 x86_mov_reg_membase (code, X86_ESI, X86_EBP, pos, 4);
3071                                 pos += 4;
3072                         }
3073                         if (cfg->used_int_regs & (1 << X86_EDI)) {
3074                                 x86_mov_reg_membase (code, X86_EDI, X86_EBP, pos, 4);
3075                                 pos += 4;
3076                         }
3077                         if (cfg->used_int_regs & (1 << X86_EBX)) {
3078                                 x86_mov_reg_membase (code, X86_EBX, X86_EBP, pos, 4);
3079                                 pos += 4;
3080                         }
3081
3082                         /* Copy arguments on the stack to our argument area */
3083                         for (i = 0; i < call->stack_usage; i += 4) {
3084                                 x86_mov_reg_membase (code, X86_EAX, X86_ESP, i, 4);
3085                                 x86_mov_membase_reg (code, X86_EBP, 8 + i, X86_EAX, 4);
3086                         }
3087         
3088                         /* restore ESP/EBP */
3089                         x86_leave (code);
3090                         offset = code - cfg->native_code;
3091                         mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_METHOD_JUMP, ins->inst_p0);
3092                         x86_jump32 (code, 0);
3093
3094                         cfg->disable_aot = TRUE;
3095                         break;
3096                 }
3097                 case OP_CHECK_THIS:
3098                         /* ensure ins->sreg1 is not NULL
3099                          * note that cmp DWORD PTR [eax], eax is one byte shorter than
3100                          * cmp DWORD PTR [eax], 0
3101                          */
3102                         x86_alu_membase_reg (code, X86_CMP, ins->sreg1, 0, ins->sreg1);
3103                         break;
3104                 case OP_ARGLIST: {
3105                         int hreg = ins->sreg1 == X86_EAX? X86_ECX: X86_EAX;
3106                         x86_push_reg (code, hreg);
3107                         x86_lea_membase (code, hreg, X86_EBP, cfg->sig_cookie);
3108                         x86_mov_membase_reg (code, ins->sreg1, 0, hreg, 4);
3109                         x86_pop_reg (code, hreg);
3110                         break;
3111                 }
3112                 case OP_FCALL:
3113                 case OP_LCALL:
3114                 case OP_VCALL:
3115                 case OP_VCALL2:
3116                 case OP_VOIDCALL:
3117                 case OP_CALL:
3118                         call = (MonoCallInst*)ins;
3119                         if (ins->flags & MONO_INST_HAS_METHOD)
3120                                 code = emit_call (cfg, code, MONO_PATCH_INFO_METHOD, call->method);
3121                         else
3122                                 code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, call->fptr);
3123                         ins->flags |= MONO_INST_GC_CALLSITE;
3124                         ins->backend.pc_offset = code - cfg->native_code;
3125                         if (call->stack_usage && !CALLCONV_IS_STDCALL (call->signature)) {
3126                                 /* a pop is one byte, while an add reg, imm is 3. So if there are 4 or 8
3127                                  * bytes to pop, we want to use pops. GCC does this (note it won't happen
3128                                  * for P4 or i686 because gcc will avoid using pop push at all. But we aren't
3129                                  * smart enough to do that optimization yet
3130                                  *
3131                                  * It turns out that on my P4, doing two pops for 8 bytes on the stack makes
3132                                  * mcs botstrap slow down. However, doing 1 pop for 4 bytes creates a small,
3133                                  * (most likely from locality benefits). People with other processors should
3134                                  * check on theirs to see what happens.
3135                                  */
3136                                 if (call->stack_usage == 4) {
3137                                         /* we want to use registers that won't get used soon, so use
3138                                          * ecx, as eax will get allocated first. edx is used by long calls,
3139                                          * so we can't use that.
3140                                          */
3141                                         
3142                                         x86_pop_reg (code, X86_ECX);
3143                                 } else {
3144                                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, call->stack_usage);
3145                                 }
3146                         }
3147                         code = emit_move_return_value (cfg, ins, code);
3148                         break;
3149                 case OP_FCALL_REG:
3150                 case OP_LCALL_REG:
3151                 case OP_VCALL_REG:
3152                 case OP_VCALL2_REG:
3153                 case OP_VOIDCALL_REG:
3154                 case OP_CALL_REG:
3155                         call = (MonoCallInst*)ins;
3156                         x86_call_reg (code, ins->sreg1);
3157                         ins->flags |= MONO_INST_GC_CALLSITE;
3158                         ins->backend.pc_offset = code - cfg->native_code;
3159                         if (call->stack_usage && !CALLCONV_IS_STDCALL (call->signature)) {
3160                                 if (call->stack_usage == 4)
3161                                         x86_pop_reg (code, X86_ECX);
3162                                 else
3163                                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, call->stack_usage);
3164                         }
3165                         code = emit_move_return_value (cfg, ins, code);
3166                         break;
3167                 case OP_FCALL_MEMBASE:
3168                 case OP_LCALL_MEMBASE:
3169                 case OP_VCALL_MEMBASE:
3170                 case OP_VCALL2_MEMBASE:
3171                 case OP_VOIDCALL_MEMBASE:
3172                 case OP_CALL_MEMBASE:
3173                         call = (MonoCallInst*)ins;
3174
3175                         x86_call_membase (code, ins->sreg1, ins->inst_offset);
3176                         ins->flags |= MONO_INST_GC_CALLSITE;
3177                         ins->backend.pc_offset = code - cfg->native_code;
3178                         if (call->stack_usage && !CALLCONV_IS_STDCALL (call->signature)) {
3179                                 if (call->stack_usage == 4)
3180                                         x86_pop_reg (code, X86_ECX);
3181                                 else
3182                                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, call->stack_usage);
3183                         }
3184                         code = emit_move_return_value (cfg, ins, code);
3185                         break;
3186                 case OP_X86_PUSH:
3187                         x86_push_reg (code, ins->sreg1);
3188                         break;
3189                 case OP_X86_PUSH_IMM:
3190                         x86_push_imm (code, ins->inst_imm);
3191                         break;
3192                 case OP_X86_PUSH_MEMBASE:
3193                         x86_push_membase (code, ins->inst_basereg, ins->inst_offset);
3194                         break;
3195                 case OP_X86_PUSH_OBJ: 
3196                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, ins->inst_imm);
3197                         x86_push_reg (code, X86_EDI);
3198                         x86_push_reg (code, X86_ESI);
3199                         x86_push_reg (code, X86_ECX);
3200                         if (ins->inst_offset)
3201                                 x86_lea_membase (code, X86_ESI, ins->inst_basereg, ins->inst_offset);
3202                         else
3203                                 x86_mov_reg_reg (code, X86_ESI, ins->inst_basereg, 4);
3204                         x86_lea_membase (code, X86_EDI, X86_ESP, 12);
3205                         x86_mov_reg_imm (code, X86_ECX, (ins->inst_imm >> 2));
3206                         x86_cld (code);
3207                         x86_prefix (code, X86_REP_PREFIX);
3208                         x86_movsd (code);
3209                         x86_pop_reg (code, X86_ECX);
3210                         x86_pop_reg (code, X86_ESI);
3211                         x86_pop_reg (code, X86_EDI);
3212                         break;
3213                 case OP_X86_LEA:
3214                         x86_lea_memindex (code, ins->dreg, ins->sreg1, ins->inst_imm, ins->sreg2, ins->backend.shift_amount);
3215                         break;
3216                 case OP_X86_LEA_MEMBASE:
3217                         x86_lea_membase (code, ins->dreg, ins->sreg1, ins->inst_imm);
3218                         break;
3219                 case OP_X86_XCHG:
3220                         x86_xchg_reg_reg (code, ins->sreg1, ins->sreg2, 4);
3221                         break;
3222                 case OP_LOCALLOC:
3223                         /* keep alignment */
3224                         x86_alu_reg_imm (code, X86_ADD, ins->sreg1, MONO_ARCH_LOCALLOC_ALIGNMENT - 1);
3225                         x86_alu_reg_imm (code, X86_AND, ins->sreg1, ~(MONO_ARCH_LOCALLOC_ALIGNMENT - 1));
3226                         code = mono_emit_stack_alloc (code, ins);
3227                         x86_mov_reg_reg (code, ins->dreg, X86_ESP, 4);
3228                         break;
3229                 case OP_LOCALLOC_IMM: {
3230                         guint32 size = ins->inst_imm;
3231                         size = (size + (MONO_ARCH_FRAME_ALIGNMENT - 1)) & ~ (MONO_ARCH_FRAME_ALIGNMENT - 1);
3232
3233                         if (ins->flags & MONO_INST_INIT) {
3234                                 /* FIXME: Optimize this */
3235                                 x86_mov_reg_imm (code, ins->dreg, size);
3236                                 ins->sreg1 = ins->dreg;
3237
3238                                 code = mono_emit_stack_alloc (code, ins);
3239                                 x86_mov_reg_reg (code, ins->dreg, X86_ESP, 4);
3240                         } else {
3241                                 x86_alu_reg_imm (code, X86_SUB, X86_ESP, size);
3242                                 x86_mov_reg_reg (code, ins->dreg, X86_ESP, 4);
3243                         }
3244                         break;
3245                 }
3246                 case OP_THROW: {
3247                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, MONO_ARCH_FRAME_ALIGNMENT - 4);
3248                         x86_push_reg (code, ins->sreg1);
3249                         code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, 
3250                                                           (gpointer)"mono_arch_throw_exception");
3251                         ins->flags |= MONO_INST_GC_CALLSITE;
3252                         ins->backend.pc_offset = code - cfg->native_code;
3253                         break;
3254                 }
3255                 case OP_RETHROW: {
3256                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, MONO_ARCH_FRAME_ALIGNMENT - 4);
3257                         x86_push_reg (code, ins->sreg1);
3258                         code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, 
3259                                                           (gpointer)"mono_arch_rethrow_exception");
3260                         ins->flags |= MONO_INST_GC_CALLSITE;
3261                         ins->backend.pc_offset = code - cfg->native_code;
3262                         break;
3263                 }
3264                 case OP_CALL_HANDLER:
3265                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, MONO_ARCH_FRAME_ALIGNMENT - 4);
3266                         mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_target_bb);
3267                         x86_call_imm (code, 0);
3268                         mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
3269                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, MONO_ARCH_FRAME_ALIGNMENT - 4);
3270                         break;
3271                 case OP_START_HANDLER: {
3272                         MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
3273                         x86_mov_membase_reg (code, spvar->inst_basereg, spvar->inst_offset, X86_ESP, 4);
3274                         break;
3275                 }
3276                 case OP_ENDFINALLY: {
3277                         MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
3278                         x86_mov_reg_membase (code, X86_ESP, spvar->inst_basereg, spvar->inst_offset, 4);
3279                         x86_ret (code);
3280                         break;
3281                 }
3282                 case OP_ENDFILTER: {
3283                         MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
3284                         x86_mov_reg_membase (code, X86_ESP, spvar->inst_basereg, spvar->inst_offset, 4);
3285                         /* The local allocator will put the result into EAX */
3286                         x86_ret (code);
3287                         break;
3288                 }
3289
3290                 case OP_LABEL:
3291                         ins->inst_c0 = code - cfg->native_code;
3292                         break;
3293                 case OP_BR:
3294                         if (ins->inst_target_bb->native_offset) {
3295                                 x86_jump_code (code, cfg->native_code + ins->inst_target_bb->native_offset); 
3296                         } else {
3297                                 mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb);
3298                                 if ((cfg->opt & MONO_OPT_BRANCH) &&
3299                                     x86_is_imm8 (ins->inst_target_bb->max_offset - cpos))
3300                                         x86_jump8 (code, 0);
3301                                 else 
3302                                         x86_jump32 (code, 0);
3303                         }
3304                         break;
3305                 case OP_BR_REG:
3306                         x86_jump_reg (code, ins->sreg1);
3307                         break;
3308                 case OP_CEQ:
3309                 case OP_CLT:
3310                 case OP_CLT_UN:
3311                 case OP_CGT:
3312                 case OP_CGT_UN:
3313                 case OP_CNE:
3314                 case OP_ICEQ:
3315                 case OP_ICLT:
3316                 case OP_ICLT_UN:
3317                 case OP_ICGT:
3318                 case OP_ICGT_UN:
3319                         x86_set_reg (code, cc_table [mono_opcode_to_cond (ins->opcode)], ins->dreg, cc_signed_table [mono_opcode_to_cond (ins->opcode)]);
3320                         x86_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
3321                         break;
3322                 case OP_COND_EXC_EQ:
3323                 case OP_COND_EXC_NE_UN:
3324                 case OP_COND_EXC_LT:
3325                 case OP_COND_EXC_LT_UN:
3326                 case OP_COND_EXC_GT:
3327                 case OP_COND_EXC_GT_UN:
3328                 case OP_COND_EXC_GE:
3329                 case OP_COND_EXC_GE_UN:
3330                 case OP_COND_EXC_LE:
3331                 case OP_COND_EXC_LE_UN:
3332                 case OP_COND_EXC_IEQ:
3333                 case OP_COND_EXC_INE_UN:
3334                 case OP_COND_EXC_ILT:
3335                 case OP_COND_EXC_ILT_UN:
3336                 case OP_COND_EXC_IGT:
3337                 case OP_COND_EXC_IGT_UN:
3338                 case OP_COND_EXC_IGE:
3339                 case OP_COND_EXC_IGE_UN:
3340                 case OP_COND_EXC_ILE:
3341                 case OP_COND_EXC_ILE_UN:
3342                         EMIT_COND_SYSTEM_EXCEPTION (cc_table [mono_opcode_to_cond (ins->opcode)], cc_signed_table [mono_opcode_to_cond (ins->opcode)], ins->inst_p1);
3343                         break;
3344                 case OP_COND_EXC_OV:
3345                 case OP_COND_EXC_NO:
3346                 case OP_COND_EXC_C:
3347                 case OP_COND_EXC_NC:
3348                         EMIT_COND_SYSTEM_EXCEPTION (branch_cc_table [ins->opcode - OP_COND_EXC_EQ], (ins->opcode < OP_COND_EXC_NE_UN), ins->inst_p1);
3349                         break;
3350                 case OP_COND_EXC_IOV:
3351                 case OP_COND_EXC_INO:
3352                 case OP_COND_EXC_IC:
3353                 case OP_COND_EXC_INC:
3354                         EMIT_COND_SYSTEM_EXCEPTION (branch_cc_table [ins->opcode - OP_COND_EXC_IEQ], (ins->opcode < OP_COND_EXC_INE_UN), ins->inst_p1);
3355                         break;
3356                 case OP_IBEQ:
3357                 case OP_IBNE_UN:
3358                 case OP_IBLT:
3359                 case OP_IBLT_UN:
3360                 case OP_IBGT:
3361                 case OP_IBGT_UN:
3362                 case OP_IBGE:
3363                 case OP_IBGE_UN:
3364                 case OP_IBLE:
3365                 case OP_IBLE_UN:
3366                         EMIT_COND_BRANCH (ins, cc_table [mono_opcode_to_cond (ins->opcode)], cc_signed_table [mono_opcode_to_cond (ins->opcode)]);
3367                         break;
3368
3369                 case OP_CMOV_IEQ:
3370                 case OP_CMOV_IGE:
3371                 case OP_CMOV_IGT:
3372                 case OP_CMOV_ILE:
3373                 case OP_CMOV_ILT:
3374                 case OP_CMOV_INE_UN:
3375                 case OP_CMOV_IGE_UN:
3376                 case OP_CMOV_IGT_UN:
3377                 case OP_CMOV_ILE_UN:
3378                 case OP_CMOV_ILT_UN:
3379                         g_assert (ins->dreg == ins->sreg1);
3380                         x86_cmov_reg (code, cc_table [mono_opcode_to_cond (ins->opcode)], cc_signed_table [mono_opcode_to_cond (ins->opcode)], ins->dreg, ins->sreg2);
3381                         break;
3382
3383                 /* floating point opcodes */
3384                 case OP_R8CONST: {
3385                         double d = *(double *)ins->inst_p0;
3386
3387                         if ((d == 0.0) && (mono_signbit (d) == 0)) {
3388                                 x86_fldz (code);
3389                         } else if (d == 1.0) {
3390                                 x86_fld1 (code);
3391                         } else {
3392                                 if (cfg->compile_aot) {
3393                                         guint32 *val = (guint32*)&d;
3394                                         x86_push_imm (code, val [1]);
3395                                         x86_push_imm (code, val [0]);
3396                                         x86_fld_membase (code, X86_ESP, 0, TRUE);
3397                                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 8);
3398                                 }
3399                                 else {
3400                                         mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_R8, ins->inst_p0);
3401                                         x86_fld (code, NULL, TRUE);
3402                                 }
3403                         }
3404                         break;
3405                 }
3406                 case OP_R4CONST: {
3407                         float f = *(float *)ins->inst_p0;
3408
3409                         if ((f == 0.0) && (mono_signbit (f) == 0)) {
3410                                 x86_fldz (code);
3411                         } else if (f == 1.0) {
3412                                 x86_fld1 (code);
3413                         } else {
3414                                 if (cfg->compile_aot) {
3415                                         guint32 val = *(guint32*)&f;
3416                                         x86_push_imm (code, val);
3417                                         x86_fld_membase (code, X86_ESP, 0, FALSE);
3418                                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
3419                                 }
3420                                 else {
3421                                         mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_R4, ins->inst_p0);
3422                                         x86_fld (code, NULL, FALSE);
3423                                 }
3424                         }
3425                         break;
3426                 }
3427                 case OP_STORER8_MEMBASE_REG:
3428                         x86_fst_membase (code, ins->inst_destbasereg, ins->inst_offset, TRUE, TRUE);
3429                         break;
3430                 case OP_LOADR8_MEMBASE:
3431                         x86_fld_membase (code, ins->inst_basereg, ins->inst_offset, TRUE);
3432                         break;
3433                 case OP_STORER4_MEMBASE_REG:
3434                         x86_fst_membase (code, ins->inst_destbasereg, ins->inst_offset, FALSE, TRUE);
3435                         break;
3436                 case OP_LOADR4_MEMBASE:
3437                         x86_fld_membase (code, ins->inst_basereg, ins->inst_offset, FALSE);
3438                         break;
3439                 case OP_ICONV_TO_R4:
3440                         x86_push_reg (code, ins->sreg1);
3441                         x86_fild_membase (code, X86_ESP, 0, FALSE);
3442                         /* Change precision */
3443                         x86_fst_membase (code, X86_ESP, 0, FALSE, TRUE);
3444                         x86_fld_membase (code, X86_ESP, 0, FALSE);
3445                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
3446                         break;
3447                 case OP_ICONV_TO_R8:
3448                         x86_push_reg (code, ins->sreg1);
3449                         x86_fild_membase (code, X86_ESP, 0, FALSE);
3450                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
3451                         break;
3452                 case OP_ICONV_TO_R_UN:
3453                         x86_push_imm (code, 0);
3454                         x86_push_reg (code, ins->sreg1);
3455                         x86_fild_membase (code, X86_ESP, 0, TRUE);
3456                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 8);
3457                         break;
3458                 case OP_X86_FP_LOAD_I8:
3459                         x86_fild_membase (code, ins->inst_basereg, ins->inst_offset, TRUE);
3460                         break;
3461                 case OP_X86_FP_LOAD_I4:
3462                         x86_fild_membase (code, ins->inst_basereg, ins->inst_offset, FALSE);
3463                         break;
3464                 case OP_FCONV_TO_R4:
3465                         /* Change precision */
3466                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, 4);
3467                         x86_fst_membase (code, X86_ESP, 0, FALSE, TRUE);
3468                         x86_fld_membase (code, X86_ESP, 0, FALSE);
3469                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
3470                         break;
3471                 case OP_FCONV_TO_I1:
3472                         code = emit_float_to_int (cfg, code, ins->dreg, 1, TRUE);
3473                         break;
3474                 case OP_FCONV_TO_U1:
3475                         code = emit_float_to_int (cfg, code, ins->dreg, 1, FALSE);
3476                         break;
3477                 case OP_FCONV_TO_I2:
3478                         code = emit_float_to_int (cfg, code, ins->dreg, 2, TRUE);
3479                         break;
3480                 case OP_FCONV_TO_U2:
3481                         code = emit_float_to_int (cfg, code, ins->dreg, 2, FALSE);
3482                         break;
3483                 case OP_FCONV_TO_I4:
3484                 case OP_FCONV_TO_I:
3485                         code = emit_float_to_int (cfg, code, ins->dreg, 4, TRUE);
3486                         break;
3487                 case OP_FCONV_TO_I8:
3488                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, 4);
3489                         x86_fnstcw_membase(code, X86_ESP, 0);
3490                         x86_mov_reg_membase (code, ins->dreg, X86_ESP, 0, 2);
3491                         x86_alu_reg_imm (code, X86_OR, ins->dreg, 0xc00);
3492                         x86_mov_membase_reg (code, X86_ESP, 2, ins->dreg, 2);
3493                         x86_fldcw_membase (code, X86_ESP, 2);
3494                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, 8);
3495                         x86_fist_pop_membase (code, X86_ESP, 0, TRUE);
3496                         x86_pop_reg (code, ins->dreg);
3497                         x86_pop_reg (code, ins->backend.reg3);
3498                         x86_fldcw_membase (code, X86_ESP, 0);
3499                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
3500                         break;
3501                 case OP_LCONV_TO_R8_2:
3502                         x86_push_reg (code, ins->sreg2);
3503                         x86_push_reg (code, ins->sreg1);
3504                         x86_fild_membase (code, X86_ESP, 0, TRUE);
3505                         /* Change precision */
3506                         x86_fst_membase (code, X86_ESP, 0, TRUE, TRUE);
3507                         x86_fld_membase (code, X86_ESP, 0, TRUE);
3508                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 8);
3509                         break;
3510                 case OP_LCONV_TO_R4_2:
3511                         x86_push_reg (code, ins->sreg2);
3512                         x86_push_reg (code, ins->sreg1);
3513                         x86_fild_membase (code, X86_ESP, 0, TRUE);
3514                         /* Change precision */
3515                         x86_fst_membase (code, X86_ESP, 0, FALSE, TRUE);
3516                         x86_fld_membase (code, X86_ESP, 0, FALSE);
3517                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 8);
3518                         break;
3519                 case OP_LCONV_TO_R_UN_2: { 
3520                         static guint8 mn[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x40 };
3521                         guint8 *br;
3522
3523                         /* load 64bit integer to FP stack */
3524                         x86_push_reg (code, ins->sreg2);
3525                         x86_push_reg (code, ins->sreg1);
3526                         x86_fild_membase (code, X86_ESP, 0, TRUE);
3527                         
3528                         /* test if lreg is negative */
3529                         x86_test_reg_reg (code, ins->sreg2, ins->sreg2);
3530                         br = code; x86_branch8 (code, X86_CC_GEZ, 0, TRUE);
3531         
3532                         /* add correction constant mn */
3533                         x86_fld80_mem (code, mn);
3534                         x86_fp_op_reg (code, X86_FADD, 1, TRUE);
3535
3536                         x86_patch (br, code);
3537
3538                         /* Change precision */
3539                         x86_fst_membase (code, X86_ESP, 0, TRUE, TRUE);
3540                         x86_fld_membase (code, X86_ESP, 0, TRUE);
3541
3542                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 8);
3543
3544                         break;
3545                 }
3546                 case OP_LCONV_TO_OVF_I:
3547                 case OP_LCONV_TO_OVF_I4_2: {
3548                         guint8 *br [3], *label [1];
3549                         MonoInst *tins;
3550
3551                         /* 
3552                          * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000
3553                          */
3554                         x86_test_reg_reg (code, ins->sreg1, ins->sreg1);
3555
3556                         /* If the low word top bit is set, see if we are negative */
3557                         br [0] = code; x86_branch8 (code, X86_CC_LT, 0, TRUE);
3558                         /* We are not negative (no top bit set, check for our top word to be zero */
3559                         x86_test_reg_reg (code, ins->sreg2, ins->sreg2);
3560                         br [1] = code; x86_branch8 (code, X86_CC_EQ, 0, TRUE);
3561                         label [0] = code;
3562
3563                         /* throw exception */
3564                         tins = mono_branch_optimize_exception_target (cfg, bb, "OverflowException");
3565                         if (tins) {
3566                                 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, tins->inst_true_bb);
3567                                 if ((cfg->opt & MONO_OPT_BRANCH) && x86_is_imm8 (tins->inst_true_bb->max_offset - cpos))
3568                                         x86_jump8 (code, 0);
3569                                 else
3570                                         x86_jump32 (code, 0);
3571                         } else {
3572                                 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_EXC, "OverflowException");
3573                                 x86_jump32 (code, 0);
3574                         }
3575         
3576         
3577                         x86_patch (br [0], code);
3578                         /* our top bit is set, check that top word is 0xfffffff */
3579                         x86_alu_reg_imm (code, X86_CMP, ins->sreg2, 0xffffffff);
3580                 
3581                         x86_patch (br [1], code);
3582                         /* nope, emit exception */
3583                         br [2] = code; x86_branch8 (code, X86_CC_NE, 0, TRUE);
3584                         x86_patch (br [2], label [0]);
3585
3586                         if (ins->dreg != ins->sreg1)
3587                                 x86_mov_reg_reg (code, ins->dreg, ins->sreg1, 4);
3588                         break;
3589                 }
3590                 case OP_FMOVE:
3591                         /* Not needed on the fp stack */
3592                         break;
3593                 case OP_FADD:
3594                         x86_fp_op_reg (code, X86_FADD, 1, TRUE);
3595                         break;
3596                 case OP_FSUB:
3597                         x86_fp_op_reg (code, X86_FSUB, 1, TRUE);
3598                         break;          
3599                 case OP_FMUL:
3600                         x86_fp_op_reg (code, X86_FMUL, 1, TRUE);
3601                         break;          
3602                 case OP_FDIV:
3603                         x86_fp_op_reg (code, X86_FDIV, 1, TRUE);
3604                         break;          
3605                 case OP_FNEG:
3606                         x86_fchs (code);
3607                         break;          
3608                 case OP_SIN:
3609                         x86_fsin (code);
3610                         x86_fldz (code);
3611                         x86_fp_op_reg (code, X86_FADD, 1, TRUE);
3612                         break;          
3613                 case OP_COS:
3614                         x86_fcos (code);
3615                         x86_fldz (code);
3616                         x86_fp_op_reg (code, X86_FADD, 1, TRUE);
3617                         break;          
3618                 case OP_ABS:
3619                         x86_fabs (code);
3620                         break;          
3621                 case OP_TAN: {
3622                         /* 
3623                          * it really doesn't make sense to inline all this code,
3624                          * it's here just to show that things may not be as simple 
3625                          * as they appear.
3626                          */
3627                         guchar *check_pos, *end_tan, *pop_jump;
3628                         x86_push_reg (code, X86_EAX);
3629                         x86_fptan (code);
3630                         x86_fnstsw (code);
3631                         x86_test_reg_imm (code, X86_EAX, X86_FP_C2);
3632                         check_pos = code;
3633                         x86_branch8 (code, X86_CC_NE, 0, FALSE);
3634                         x86_fstp (code, 0); /* pop the 1.0 */
3635                         end_tan = code;
3636                         x86_jump8 (code, 0);
3637                         x86_fldpi (code);
3638                         x86_fp_op (code, X86_FADD, 0);
3639                         x86_fxch (code, 1);
3640                         x86_fprem1 (code);
3641                         x86_fstsw (code);
3642                         x86_test_reg_imm (code, X86_EAX, X86_FP_C2);
3643                         pop_jump = code;
3644                         x86_branch8 (code, X86_CC_NE, 0, FALSE);
3645                         x86_fstp (code, 1);
3646                         x86_fptan (code);
3647                         x86_patch (pop_jump, code);
3648                         x86_fstp (code, 0); /* pop the 1.0 */
3649                         x86_patch (check_pos, code);
3650                         x86_patch (end_tan, code);
3651                         x86_fldz (code);
3652                         x86_fp_op_reg (code, X86_FADD, 1, TRUE);
3653                         x86_pop_reg (code, X86_EAX);
3654                         break;
3655                 }
3656                 case OP_ATAN:
3657                         x86_fld1 (code);
3658                         x86_fpatan (code);
3659                         x86_fldz (code);
3660                         x86_fp_op_reg (code, X86_FADD, 1, TRUE);
3661                         break;          
3662                 case OP_SQRT:
3663                         x86_fsqrt (code);
3664                         break;
3665                 case OP_ROUND:
3666                         x86_frndint (code);
3667                         break;
3668                 case OP_IMIN:
3669                         g_assert (cfg->opt & MONO_OPT_CMOV);
3670                         g_assert (ins->dreg == ins->sreg1);
3671                         x86_alu_reg_reg (code, X86_CMP, ins->sreg1, ins->sreg2);
3672                         x86_cmov_reg (code, X86_CC_GT, TRUE, ins->dreg, ins->sreg2);
3673                         break;
3674                 case OP_IMIN_UN:
3675                         g_assert (cfg->opt & MONO_OPT_CMOV);
3676                         g_assert (ins->dreg == ins->sreg1);
3677                         x86_alu_reg_reg (code, X86_CMP, ins->sreg1, ins->sreg2);
3678                         x86_cmov_reg (code, X86_CC_GT, FALSE, ins->dreg, ins->sreg2);
3679                         break;
3680                 case OP_IMAX:
3681                         g_assert (cfg->opt & MONO_OPT_CMOV);
3682                         g_assert (ins->dreg == ins->sreg1);
3683                         x86_alu_reg_reg (code, X86_CMP, ins->sreg1, ins->sreg2);
3684                         x86_cmov_reg (code, X86_CC_LT, TRUE, ins->dreg, ins->sreg2);
3685                         break;
3686                 case OP_IMAX_UN:
3687                         g_assert (cfg->opt & MONO_OPT_CMOV);
3688                         g_assert (ins->dreg == ins->sreg1);
3689                         x86_alu_reg_reg (code, X86_CMP, ins->sreg1, ins->sreg2);
3690                         x86_cmov_reg (code, X86_CC_LT, FALSE, ins->dreg, ins->sreg2);
3691                         break;
3692                 case OP_X86_FPOP:
3693                         x86_fstp (code, 0);
3694                         break;
3695                 case OP_X86_FXCH:
3696                         x86_fxch (code, ins->inst_imm);
3697                         break;
3698                 case OP_FREM: {
3699                         guint8 *l1, *l2;
3700
3701                         x86_push_reg (code, X86_EAX);
3702                         /* we need to exchange ST(0) with ST(1) */
3703                         x86_fxch (code, 1);
3704
3705                         /* this requires a loop, because fprem somtimes 
3706                          * returns a partial remainder */
3707                         l1 = code;
3708                         /* looks like MS is using fprem instead of the IEEE compatible fprem1 */
3709                         /* x86_fprem1 (code); */
3710                         x86_fprem (code);
3711                         x86_fnstsw (code);
3712                         x86_alu_reg_imm (code, X86_AND, X86_EAX, X86_FP_C2);
3713                         l2 = code + 2;
3714                         x86_branch8 (code, X86_CC_NE, l1 - l2, FALSE);
3715
3716                         /* pop result */
3717                         x86_fstp (code, 1);
3718
3719                         x86_pop_reg (code, X86_EAX);
3720                         break;
3721                 }
3722                 case OP_FCOMPARE:
3723                         if (cfg->opt & MONO_OPT_FCMOV) {
3724                                 x86_fcomip (code, 1);
3725                                 x86_fstp (code, 0);
3726                                 break;
3727                         }
3728                         /* this overwrites EAX */
3729                         EMIT_FPCOMPARE(code);
3730                         x86_alu_reg_imm (code, X86_AND, X86_EAX, X86_FP_CC_MASK);
3731                         break;
3732                 case OP_FCEQ:
3733                         if (cfg->opt & MONO_OPT_FCMOV) {
3734                                 /* zeroing the register at the start results in 
3735                                  * shorter and faster code (we can also remove the widening op)
3736                                  */
3737                                 guchar *unordered_check;
3738                                 x86_alu_reg_reg (code, X86_XOR, ins->dreg, ins->dreg);
3739                                 x86_fcomip (code, 1);
3740                                 x86_fstp (code, 0);
3741                                 unordered_check = code;
3742                                 x86_branch8 (code, X86_CC_P, 0, FALSE);
3743                                 x86_set_reg (code, X86_CC_EQ, ins->dreg, FALSE);
3744                                 x86_patch (unordered_check, code);
3745                                 break;
3746                         }
3747                         if (ins->dreg != X86_EAX) 
3748                                 x86_push_reg (code, X86_EAX);
3749
3750                         EMIT_FPCOMPARE(code);
3751                         x86_alu_reg_imm (code, X86_AND, X86_EAX, X86_FP_CC_MASK);
3752                         x86_alu_reg_imm (code, X86_CMP, X86_EAX, 0x4000);
3753                         x86_set_reg (code, X86_CC_EQ, ins->dreg, TRUE);
3754                         x86_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
3755
3756                         if (ins->dreg != X86_EAX) 
3757                                 x86_pop_reg (code, X86_EAX);
3758                         break;
3759                 case OP_FCLT:
3760                 case OP_FCLT_UN:
3761                         if (cfg->opt & MONO_OPT_FCMOV) {
3762                                 /* zeroing the register at the start results in 
3763                                  * shorter and faster code (we can also remove the widening op)
3764                                  */
3765                                 x86_alu_reg_reg (code, X86_XOR, ins->dreg, ins->dreg);
3766                                 x86_fcomip (code, 1);
3767                                 x86_fstp (code, 0);
3768                                 if (ins->opcode == OP_FCLT_UN) {
3769                                         guchar *unordered_check = code;
3770                                         guchar *jump_to_end;
3771                                         x86_branch8 (code, X86_CC_P, 0, FALSE);
3772                                         x86_set_reg (code, X86_CC_GT, ins->dreg, FALSE);
3773                                         jump_to_end = code;
3774                                         x86_jump8 (code, 0);
3775                                         x86_patch (unordered_check, code);
3776                                         x86_inc_reg (code, ins->dreg);
3777                                         x86_patch (jump_to_end, code);
3778                                 } else {
3779                                         x86_set_reg (code, X86_CC_GT, ins->dreg, FALSE);
3780                                 }
3781                                 break;
3782                         }
3783                         if (ins->dreg != X86_EAX) 
3784                                 x86_push_reg (code, X86_EAX);
3785
3786                         EMIT_FPCOMPARE(code);
3787                         x86_alu_reg_imm (code, X86_AND, X86_EAX, X86_FP_CC_MASK);
3788                         if (ins->opcode == OP_FCLT_UN) {
3789                                 guchar *is_not_zero_check, *end_jump;
3790                                 is_not_zero_check = code;
3791                                 x86_branch8 (code, X86_CC_NZ, 0, TRUE);
3792                                 end_jump = code;
3793                                 x86_jump8 (code, 0);
3794                                 x86_patch (is_not_zero_check, code);
3795                                 x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_CC_MASK);
3796
3797                                 x86_patch (end_jump, code);
3798                         }
3799                         x86_set_reg (code, X86_CC_EQ, ins->dreg, TRUE);
3800                         x86_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
3801
3802                         if (ins->dreg != X86_EAX) 
3803                                 x86_pop_reg (code, X86_EAX);
3804                         break;
3805                 case OP_FCGT:
3806                 case OP_FCGT_UN:
3807                         if (cfg->opt & MONO_OPT_FCMOV) {
3808                                 /* zeroing the register at the start results in 
3809                                  * shorter and faster code (we can also remove the widening op)
3810                                  */
3811                                 guchar *unordered_check;
3812                                 x86_alu_reg_reg (code, X86_XOR, ins->dreg, ins->dreg);
3813                                 x86_fcomip (code, 1);
3814                                 x86_fstp (code, 0);
3815                                 if (ins->opcode == OP_FCGT) {
3816                                         unordered_check = code;
3817                                         x86_branch8 (code, X86_CC_P, 0, FALSE);
3818                                         x86_set_reg (code, X86_CC_LT, ins->dreg, FALSE);
3819                                         x86_patch (unordered_check, code);
3820                                 } else {
3821                                         x86_set_reg (code, X86_CC_LT, ins->dreg, FALSE);
3822                                 }
3823                                 break;
3824                         }
3825                         if (ins->dreg != X86_EAX) 
3826                                 x86_push_reg (code, X86_EAX);
3827
3828                         EMIT_FPCOMPARE(code);
3829                         x86_alu_reg_imm (code, X86_AND, X86_EAX, X86_FP_CC_MASK);
3830                         x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_C0);
3831                         if (ins->opcode == OP_FCGT_UN) {
3832                                 guchar *is_not_zero_check, *end_jump;
3833                                 is_not_zero_check = code;
3834                                 x86_branch8 (code, X86_CC_NZ, 0, TRUE);
3835                                 end_jump = code;
3836                                 x86_jump8 (code, 0);
3837                                 x86_patch (is_not_zero_check, code);
3838                                 x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_CC_MASK);
3839         
3840                                 x86_patch (end_jump, code);
3841                         }
3842                         x86_set_reg (code, X86_CC_EQ, ins->dreg, TRUE);
3843                         x86_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
3844
3845                         if (ins->dreg != X86_EAX) 
3846                                 x86_pop_reg (code, X86_EAX);
3847                         break;
3848                 case OP_FBEQ:
3849                         if (cfg->opt & MONO_OPT_FCMOV) {
3850                                 guchar *jump = code;
3851                                 x86_branch8 (code, X86_CC_P, 0, TRUE);
3852                                 EMIT_COND_BRANCH (ins, X86_CC_EQ, FALSE);
3853                                 x86_patch (jump, code);
3854                                 break;
3855                         }
3856                         x86_alu_reg_imm (code, X86_CMP, X86_EAX, 0x4000);
3857                         EMIT_COND_BRANCH (ins, X86_CC_EQ, TRUE);
3858                         break;
3859                 case OP_FBNE_UN:
3860                         /* Branch if C013 != 100 */
3861                         if (cfg->opt & MONO_OPT_FCMOV) {
3862                                 /* branch if !ZF or (PF|CF) */
3863                                 EMIT_COND_BRANCH (ins, X86_CC_NE, FALSE);
3864                                 EMIT_COND_BRANCH (ins, X86_CC_P, FALSE);
3865                                 EMIT_COND_BRANCH (ins, X86_CC_B, FALSE);
3866                                 break;
3867                         }
3868                         x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_C3);
3869                         EMIT_COND_BRANCH (ins, X86_CC_NE, FALSE);
3870                         break;
3871                 case OP_FBLT:
3872                         if (cfg->opt & MONO_OPT_FCMOV) {
3873                                 EMIT_COND_BRANCH (ins, X86_CC_GT, FALSE);
3874                                 break;
3875                         }
3876                         EMIT_COND_BRANCH (ins, X86_CC_EQ, FALSE);
3877                         break;
3878                 case OP_FBLT_UN:
3879                         if (cfg->opt & MONO_OPT_FCMOV) {
3880                                 EMIT_COND_BRANCH (ins, X86_CC_P, FALSE);
3881                                 EMIT_COND_BRANCH (ins, X86_CC_GT, FALSE);
3882                                 break;
3883                         }
3884                         if (ins->opcode == OP_FBLT_UN) {
3885                                 guchar *is_not_zero_check, *end_jump;
3886                                 is_not_zero_check = code;
3887                                 x86_branch8 (code, X86_CC_NZ, 0, TRUE);
3888                                 end_jump = code;
3889                                 x86_jump8 (code, 0);
3890                                 x86_patch (is_not_zero_check, code);
3891                                 x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_CC_MASK);
3892
3893                                 x86_patch (end_jump, code);
3894                         }
3895                         EMIT_COND_BRANCH (ins, X86_CC_EQ, FALSE);
3896                         break;
3897                 case OP_FBGT:
3898                 case OP_FBGT_UN:
3899                         if (cfg->opt & MONO_OPT_FCMOV) {
3900                                 if (ins->opcode == OP_FBGT) {
3901                                         guchar *br1;
3902
3903                                         /* skip branch if C1=1 */
3904                                         br1 = code;
3905                                         x86_branch8 (code, X86_CC_P, 0, FALSE);
3906                                         /* branch if (C0 | C3) = 1 */
3907                                         EMIT_COND_BRANCH (ins, X86_CC_LT, FALSE);
3908                                         x86_patch (br1, code);
3909                                 } else {
3910                                         EMIT_COND_BRANCH (ins, X86_CC_LT, FALSE);
3911                                 }
3912                                 break;
3913                         }
3914                         x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_C0);
3915                         if (ins->opcode == OP_FBGT_UN) {
3916                                 guchar *is_not_zero_check, *end_jump;
3917                                 is_not_zero_check = code;
3918                                 x86_branch8 (code, X86_CC_NZ, 0, TRUE);
3919                                 end_jump = code;
3920                                 x86_jump8 (code, 0);
3921                                 x86_patch (is_not_zero_check, code);
3922                                 x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_CC_MASK);
3923
3924                                 x86_patch (end_jump, code);
3925                         }
3926                         EMIT_COND_BRANCH (ins, X86_CC_EQ, FALSE);
3927                         break;
3928                 case OP_FBGE:
3929                         /* Branch if C013 == 100 or 001 */
3930                         if (cfg->opt & MONO_OPT_FCMOV) {
3931                                 guchar *br1;
3932
3933                                 /* skip branch if C1=1 */
3934                                 br1 = code;
3935                                 x86_branch8 (code, X86_CC_P, 0, FALSE);
3936                                 /* branch if (C0 | C3) = 1 */
3937                                 EMIT_COND_BRANCH (ins, X86_CC_BE, FALSE);
3938                                 x86_patch (br1, code);
3939                                 break;
3940                         }
3941                         x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_C0);
3942                         EMIT_COND_BRANCH (ins, X86_CC_EQ, FALSE);
3943                         x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_C3);
3944                         EMIT_COND_BRANCH (ins, X86_CC_EQ, FALSE);
3945                         break;
3946                 case OP_FBGE_UN:
3947                         /* Branch if C013 == 000 */
3948                         if (cfg->opt & MONO_OPT_FCMOV) {
3949                                 EMIT_COND_BRANCH (ins, X86_CC_LE, FALSE);
3950                                 break;
3951                         }
3952                         EMIT_COND_BRANCH (ins, X86_CC_NE, FALSE);
3953                         break;
3954                 case OP_FBLE:
3955                         /* Branch if C013=000 or 100 */
3956                         if (cfg->opt & MONO_OPT_FCMOV) {
3957                                 guchar *br1;
3958
3959                                 /* skip branch if C1=1 */
3960                                 br1 = code;
3961                                 x86_branch8 (code, X86_CC_P, 0, FALSE);
3962                                 /* branch if C0=0 */
3963                                 EMIT_COND_BRANCH (ins, X86_CC_NB, FALSE);
3964                                 x86_patch (br1, code);
3965                                 break;
3966                         }
3967                         x86_alu_reg_imm (code, X86_AND, X86_EAX, (X86_FP_C0|X86_FP_C1));
3968                         x86_alu_reg_imm (code, X86_CMP, X86_EAX, 0);
3969                         EMIT_COND_BRANCH (ins, X86_CC_EQ, FALSE);
3970                         break;
3971                 case OP_FBLE_UN:
3972                         /* Branch if C013 != 001 */
3973                         if (cfg->opt & MONO_OPT_FCMOV) {
3974                                 EMIT_COND_BRANCH (ins, X86_CC_P, FALSE);
3975                                 EMIT_COND_BRANCH (ins, X86_CC_GE, FALSE);
3976                                 break;
3977                         }
3978                         x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_C0);
3979                         EMIT_COND_BRANCH (ins, X86_CC_NE, FALSE);
3980                         break;
3981                 case OP_CKFINITE: {
3982                         guchar *br1;
3983                         x86_push_reg (code, X86_EAX);
3984                         x86_fxam (code);
3985                         x86_fnstsw (code);
3986                         x86_alu_reg_imm (code, X86_AND, X86_EAX, 0x4100);
3987                         x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_C0);
3988                         x86_pop_reg (code, X86_EAX);
3989
3990                         /* Have to clean up the fp stack before throwing the exception */
3991                         br1 = code;
3992                         x86_branch8 (code, X86_CC_NE, 0, FALSE);
3993
3994                         x86_fstp (code, 0);                     
3995                         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "ArithmeticException");
3996
3997                         x86_patch (br1, code);
3998                         break;
3999                 }
4000                 case OP_TLS_GET: {
4001                         code = mono_x86_emit_tls_get (code, ins->dreg, ins->inst_offset);
4002                         break;
4003                 }
4004                 case OP_MEMORY_BARRIER: {
4005                         /* http://blogs.sun.com/dave/resource/NHM-Pipeline-Blog-V2.txt */
4006                         x86_prefix (code, X86_LOCK_PREFIX);
4007                         x86_alu_membase_imm (code, X86_ADD, X86_ESP, 0, 0);
4008                         break;
4009                 }
4010                 case OP_ATOMIC_ADD_I4: {
4011                         int dreg = ins->dreg;
4012
4013                         if (dreg == ins->inst_basereg) {
4014                                 x86_push_reg (code, ins->sreg2);
4015                                 dreg = ins->sreg2;
4016                         } 
4017                         
4018                         if (dreg != ins->sreg2)
4019                                 x86_mov_reg_reg (code, ins->dreg, ins->sreg2, 4);
4020
4021                         x86_prefix (code, X86_LOCK_PREFIX);
4022                         x86_xadd_membase_reg (code, ins->inst_basereg, ins->inst_offset, dreg, 4);
4023
4024                         if (dreg != ins->dreg) {
4025                                 x86_mov_reg_reg (code, ins->dreg, dreg, 4);
4026                                 x86_pop_reg (code, dreg);
4027                         }
4028
4029                         break;
4030                 }
4031                 case OP_ATOMIC_ADD_NEW_I4: {
4032                         int dreg = ins->dreg;
4033
4034                         /* hack: limit in regalloc, dreg != sreg1 && dreg != sreg2 */
4035                         if (ins->sreg2 == dreg) {
4036                                 if (dreg == X86_EBX) {
4037                                         dreg = X86_EDI;
4038                                         if (ins->inst_basereg == X86_EDI)
4039                                                 dreg = X86_ESI;
4040                                 } else {
4041                                         dreg = X86_EBX;
4042                                         if (ins->inst_basereg == X86_EBX)
4043                                                 dreg = X86_EDI;
4044                                 }
4045                         } else if (ins->inst_basereg == dreg) {
4046                                 if (dreg == X86_EBX) {
4047                                         dreg = X86_EDI;
4048                                         if (ins->sreg2 == X86_EDI)
4049                                                 dreg = X86_ESI;
4050                                 } else {
4051                                         dreg = X86_EBX;
4052                                         if (ins->sreg2 == X86_EBX)
4053                                                 dreg = X86_EDI;
4054                                 }
4055                         }
4056
4057                         if (dreg != ins->dreg) {
4058                                 x86_push_reg (code, dreg);
4059                         }
4060
4061                         x86_mov_reg_reg (code, dreg, ins->sreg2, 4);
4062                         x86_prefix (code, X86_LOCK_PREFIX);
4063                         x86_xadd_membase_reg (code, ins->inst_basereg, ins->inst_offset, dreg, 4);
4064                         /* dreg contains the old value, add with sreg2 value */
4065                         x86_alu_reg_reg (code, X86_ADD, dreg, ins->sreg2);
4066                         
4067                         if (ins->dreg != dreg) {
4068                                 x86_mov_reg_reg (code, ins->dreg, dreg, 4);
4069                                 x86_pop_reg (code, dreg);
4070                         }
4071
4072                         break;
4073                 }
4074                 case OP_ATOMIC_EXCHANGE_I4: {
4075                         guchar *br[2];
4076                         int sreg2 = ins->sreg2;
4077                         int breg = ins->inst_basereg;
4078
4079                         /* cmpxchg uses eax as comperand, need to make sure we can use it
4080                          * hack to overcome limits in x86 reg allocator 
4081                          * (req: dreg == eax and sreg2 != eax and breg != eax) 
4082                          */
4083                         g_assert (ins->dreg == X86_EAX);
4084                         
4085                         /* We need the EAX reg for the cmpxchg */
4086                         if (ins->sreg2 == X86_EAX) {
4087                                 sreg2 = (breg == X86_EDX) ? X86_EBX : X86_EDX;
4088                                 x86_push_reg (code, sreg2);
4089                                 x86_mov_reg_reg (code, sreg2, X86_EAX, 4);
4090                         }
4091
4092                         if (breg == X86_EAX) {
4093                                 breg = (sreg2 == X86_ESI) ? X86_EDI : X86_ESI;
4094                                 x86_push_reg (code, breg);
4095                                 x86_mov_reg_reg (code, breg, X86_EAX, 4);
4096                         }
4097
4098                         x86_mov_reg_membase (code, X86_EAX, breg, ins->inst_offset, 4);
4099
4100                         br [0] = code; x86_prefix (code, X86_LOCK_PREFIX);
4101                         x86_cmpxchg_membase_reg (code, breg, ins->inst_offset, sreg2);
4102                         br [1] = code; x86_branch8 (code, X86_CC_NE, -1, FALSE);
4103                         x86_patch (br [1], br [0]);
4104
4105                         if (breg != ins->inst_basereg)
4106                                 x86_pop_reg (code, breg);
4107
4108                         if (ins->sreg2 != sreg2)
4109                                 x86_pop_reg (code, sreg2);
4110
4111                         break;
4112                 }
4113                 case OP_ATOMIC_CAS_I4: {
4114                         g_assert (ins->dreg == X86_EAX);
4115                         g_assert (ins->sreg3 == X86_EAX);
4116                         g_assert (ins->sreg1 != X86_EAX);
4117                         g_assert (ins->sreg1 != ins->sreg2);
4118
4119                         x86_prefix (code, X86_LOCK_PREFIX);
4120                         x86_cmpxchg_membase_reg (code, ins->sreg1, ins->inst_offset, ins->sreg2);
4121                         break;
4122                 }
4123                 case OP_CARD_TABLE_WBARRIER: {
4124                         int ptr = ins->sreg1;
4125                         int value = ins->sreg2;
4126                         guchar *br;
4127                         int nursery_shift, card_table_shift;
4128                         gpointer card_table_mask;
4129                         size_t nursery_size;
4130                         gulong card_table = (gulong)mono_gc_get_card_table (&card_table_shift, &card_table_mask);
4131                         gulong nursery_start = (gulong)mono_gc_get_nursery (&nursery_shift, &nursery_size);
4132
4133                         /*
4134                          * We need one register we can clobber, we choose EDX and make sreg1
4135                          * fixed EAX to work around limitations in the local register allocator.
4136                          * sreg2 might get allocated to EDX, but that is not a problem since
4137                          * we use it before clobbering EDX.
4138                          */
4139                         g_assert (ins->sreg1 == X86_EAX);
4140
4141                         /*
4142                          * This is the code we produce:
4143                          *
4144                          *   edx = value
4145                          *   edx >>= nursery_shift
4146                          *   cmp edx, (nursery_start >> nursery_shift)
4147                          *   jne done
4148                          *   edx = ptr
4149                          *   edx >>= card_table_shift
4150                          *   card_table[edx] = 1
4151                          * done:
4152                          */
4153
4154                         if (value != X86_EDX)
4155                                 x86_mov_reg_reg (code, X86_EDX, value, 4);
4156                         x86_shift_reg_imm (code, X86_SHR, X86_EDX, nursery_shift);
4157                         x86_alu_reg_imm (code, X86_CMP, X86_EDX, nursery_start >> nursery_shift);
4158                         br = code; x86_branch8 (code, X86_CC_NE, -1, FALSE);
4159                         x86_mov_reg_reg (code, X86_EDX, ptr, 4);
4160                         x86_shift_reg_imm (code, X86_SHR, X86_EDX, card_table_shift);
4161                         if (card_table_mask)
4162                                 x86_alu_reg_imm (code, X86_AND, X86_EDX, (int)card_table_mask);
4163                         x86_mov_membase_imm (code, X86_EDX, card_table, 1, 1);
4164                         x86_patch (br, code);
4165                         break;
4166                 }
4167 #ifdef MONO_ARCH_SIMD_INTRINSICS
4168                 case OP_ADDPS:
4169                         x86_sse_alu_ps_reg_reg (code, X86_SSE_ADD, ins->sreg1, ins->sreg2);
4170                         break;
4171                 case OP_DIVPS:
4172                         x86_sse_alu_ps_reg_reg (code, X86_SSE_DIV, ins->sreg1, ins->sreg2);
4173                         break;
4174                 case OP_MULPS:
4175                         x86_sse_alu_ps_reg_reg (code, X86_SSE_MUL, ins->sreg1, ins->sreg2);
4176                         break;
4177                 case OP_SUBPS:
4178                         x86_sse_alu_ps_reg_reg (code, X86_SSE_SUB, ins->sreg1, ins->sreg2);
4179                         break;
4180                 case OP_MAXPS:
4181                         x86_sse_alu_ps_reg_reg (code, X86_SSE_MAX, ins->sreg1, ins->sreg2);
4182                         break;
4183                 case OP_MINPS:
4184                         x86_sse_alu_ps_reg_reg (code, X86_SSE_MIN, ins->sreg1, ins->sreg2);
4185                         break;
4186                 case OP_COMPPS:
4187                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4188                         x86_sse_alu_ps_reg_reg_imm (code, X86_SSE_COMP, ins->sreg1, ins->sreg2, ins->inst_c0);
4189                         break;
4190                 case OP_ANDPS:
4191                         x86_sse_alu_ps_reg_reg (code, X86_SSE_AND, ins->sreg1, ins->sreg2);
4192                         break;
4193                 case OP_ANDNPS:
4194                         x86_sse_alu_ps_reg_reg (code, X86_SSE_ANDN, ins->sreg1, ins->sreg2);
4195                         break;
4196                 case OP_ORPS:
4197                         x86_sse_alu_ps_reg_reg (code, X86_SSE_OR, ins->sreg1, ins->sreg2);
4198                         break;
4199                 case OP_XORPS:
4200                         x86_sse_alu_ps_reg_reg (code, X86_SSE_XOR, ins->sreg1, ins->sreg2);
4201                         break;
4202                 case OP_SQRTPS:
4203                         x86_sse_alu_ps_reg_reg (code, X86_SSE_SQRT, ins->dreg, ins->sreg1);
4204                         break;
4205                 case OP_RSQRTPS:
4206                         x86_sse_alu_ps_reg_reg (code, X86_SSE_RSQRT, ins->dreg, ins->sreg1);
4207                         break;
4208                 case OP_RCPPS:
4209                         x86_sse_alu_ps_reg_reg (code, X86_SSE_RCP, ins->dreg, ins->sreg1);
4210                         break;
4211                 case OP_ADDSUBPS:
4212                         x86_sse_alu_sd_reg_reg (code, X86_SSE_ADDSUB, ins->sreg1, ins->sreg2);
4213                         break;
4214                 case OP_HADDPS:
4215                         x86_sse_alu_sd_reg_reg (code, X86_SSE_HADD, ins->sreg1, ins->sreg2);
4216                         break;
4217                 case OP_HSUBPS:
4218                         x86_sse_alu_sd_reg_reg (code, X86_SSE_HSUB, ins->sreg1, ins->sreg2);
4219                         break;
4220                 case OP_DUPPS_HIGH:
4221                         x86_sse_alu_ss_reg_reg (code, X86_SSE_MOVSHDUP, ins->dreg, ins->sreg1);
4222                         break;
4223                 case OP_DUPPS_LOW:
4224                         x86_sse_alu_ss_reg_reg (code, X86_SSE_MOVSLDUP, ins->dreg, ins->sreg1);
4225                         break;
4226
4227                 case OP_PSHUFLEW_HIGH:
4228                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4229                         x86_pshufw_reg_reg (code, ins->dreg, ins->sreg1, ins->inst_c0, 1);
4230                         break;
4231                 case OP_PSHUFLEW_LOW:
4232                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4233                         x86_pshufw_reg_reg (code, ins->dreg, ins->sreg1, ins->inst_c0, 0);
4234                         break;
4235                 case OP_PSHUFLED:
4236                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4237                         x86_sse_shift_reg_imm (code, X86_SSE_PSHUFD, ins->dreg, ins->sreg1, ins->inst_c0);
4238                         break;
4239                 case OP_SHUFPS:
4240                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4241                         x86_sse_alu_reg_reg_imm8 (code, X86_SSE_SHUFP, ins->sreg1, ins->sreg2, ins->inst_c0);
4242                         break; 
4243                 case OP_SHUFPD:
4244                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4245                         x86_sse_alu_pd_reg_reg_imm8 (code, X86_SSE_SHUFP, ins->sreg1, ins->sreg2, ins->inst_c0);
4246                         break; 
4247
4248                 case OP_ADDPD:
4249                         x86_sse_alu_pd_reg_reg (code, X86_SSE_ADD, ins->sreg1, ins->sreg2);
4250                         break;
4251                 case OP_DIVPD:
4252                         x86_sse_alu_pd_reg_reg (code, X86_SSE_DIV, ins->sreg1, ins->sreg2);
4253                         break;
4254                 case OP_MULPD:
4255                         x86_sse_alu_pd_reg_reg (code, X86_SSE_MUL, ins->sreg1, ins->sreg2);
4256                         break;
4257                 case OP_SUBPD:
4258                         x86_sse_alu_pd_reg_reg (code, X86_SSE_SUB, ins->sreg1, ins->sreg2);
4259                         break;
4260                 case OP_MAXPD:
4261                         x86_sse_alu_pd_reg_reg (code, X86_SSE_MAX, ins->sreg1, ins->sreg2);
4262                         break;
4263                 case OP_MINPD:
4264                         x86_sse_alu_pd_reg_reg (code, X86_SSE_MIN, ins->sreg1, ins->sreg2);
4265                         break;
4266                 case OP_COMPPD:
4267                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4268                         x86_sse_alu_pd_reg_reg_imm (code, X86_SSE_COMP, ins->sreg1, ins->sreg2, ins->inst_c0);
4269                         break;
4270                 case OP_ANDPD:
4271                         x86_sse_alu_pd_reg_reg (code, X86_SSE_AND, ins->sreg1, ins->sreg2);
4272                         break;
4273                 case OP_ANDNPD:
4274                         x86_sse_alu_pd_reg_reg (code, X86_SSE_ANDN, ins->sreg1, ins->sreg2);
4275                         break;
4276                 case OP_ORPD:
4277                         x86_sse_alu_pd_reg_reg (code, X86_SSE_OR, ins->sreg1, ins->sreg2);
4278                         break;
4279                 case OP_XORPD:
4280                         x86_sse_alu_pd_reg_reg (code, X86_SSE_XOR, ins->sreg1, ins->sreg2);
4281                         break;
4282                 case OP_SQRTPD:
4283                         x86_sse_alu_pd_reg_reg (code, X86_SSE_SQRT, ins->dreg, ins->sreg1);
4284                         break;
4285                 case OP_ADDSUBPD:
4286                         x86_sse_alu_pd_reg_reg (code, X86_SSE_ADDSUB, ins->sreg1, ins->sreg2);
4287                         break;
4288                 case OP_HADDPD:
4289                         x86_sse_alu_pd_reg_reg (code, X86_SSE_HADD, ins->sreg1, ins->sreg2);
4290                         break;
4291                 case OP_HSUBPD:
4292                         x86_sse_alu_pd_reg_reg (code, X86_SSE_HSUB, ins->sreg1, ins->sreg2);
4293                         break;
4294                 case OP_DUPPD:
4295                         x86_sse_alu_sd_reg_reg (code, X86_SSE_MOVDDUP, ins->dreg, ins->sreg1);
4296                         break;
4297                         
4298                 case OP_EXTRACT_MASK:
4299                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PMOVMSKB, ins->dreg, ins->sreg1);
4300                         break;
4301         
4302                 case OP_PAND:
4303                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PAND, ins->sreg1, ins->sreg2);
4304                         break;
4305                 case OP_POR:
4306                         x86_sse_alu_pd_reg_reg (code, X86_SSE_POR, ins->sreg1, ins->sreg2);
4307                         break;
4308                 case OP_PXOR:
4309                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PXOR, ins->sreg1, ins->sreg2);
4310                         break;
4311
4312                 case OP_PADDB:
4313                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PADDB, ins->sreg1, ins->sreg2);
4314                         break;
4315                 case OP_PADDW:
4316                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PADDW, ins->sreg1, ins->sreg2);
4317                         break;
4318                 case OP_PADDD:
4319                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PADDD, ins->sreg1, ins->sreg2);
4320                         break;
4321                 case OP_PADDQ:
4322                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PADDQ, ins->sreg1, ins->sreg2);
4323                         break;
4324
4325                 case OP_PSUBB:
4326                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PSUBB, ins->sreg1, ins->sreg2);
4327                         break;
4328                 case OP_PSUBW:
4329                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PSUBW, ins->sreg1, ins->sreg2);
4330                         break;
4331                 case OP_PSUBD:
4332                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PSUBD, ins->sreg1, ins->sreg2);
4333                         break;
4334                 case OP_PSUBQ:
4335                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PSUBQ, ins->sreg1, ins->sreg2);
4336                         break;
4337
4338                 case OP_PMAXB_UN:
4339                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PMAXUB, ins->sreg1, ins->sreg2);
4340                         break;
4341                 case OP_PMAXW_UN:
4342                         x86_sse_alu_sse41_reg_reg (code, X86_SSE_PMAXUW, ins->sreg1, ins->sreg2);
4343                         break;
4344                 case OP_PMAXD_UN:
4345                         x86_sse_alu_sse41_reg_reg (code, X86_SSE_PMAXUD, ins->sreg1, ins->sreg2);
4346                         break;
4347                 
4348                 case OP_PMAXB:
4349                         x86_sse_alu_sse41_reg_reg (code, X86_SSE_PMAXSB, ins->sreg1, ins->sreg2);
4350                         break;
4351                 case OP_PMAXW:
4352                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PMAXSW, ins->sreg1, ins->sreg2);
4353                         break;
4354                 case OP_PMAXD:
4355                         x86_sse_alu_sse41_reg_reg (code, X86_SSE_PMAXSD, ins->sreg1, ins->sreg2);
4356                         break;
4357
4358                 case OP_PAVGB_UN:
4359                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PAVGB, ins->sreg1, ins->sreg2);
4360                         break;
4361                 case OP_PAVGW_UN:
4362                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PAVGW, ins->sreg1, ins->sreg2);
4363                         break;
4364
4365                 case OP_PMINB_UN:
4366                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PMINUB, ins->sreg1, ins->sreg2);
4367                         break;
4368                 case OP_PMINW_UN:
4369                         x86_sse_alu_sse41_reg_reg (code, X86_SSE_PMINUW, ins->sreg1, ins->sreg2);
4370                         break;
4371                 case OP_PMIND_UN:
4372                         x86_sse_alu_sse41_reg_reg (code, X86_SSE_PMINUD, ins->sreg1, ins->sreg2);
4373                         break;
4374
4375                 case OP_PMINB:
4376                         x86_sse_alu_sse41_reg_reg (code, X86_SSE_PMINSB, ins->sreg1, ins->sreg2);
4377                         break;
4378                 case OP_PMINW:
4379                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PMINSW, ins->sreg1, ins->sreg2);
4380                         break;
4381                 case OP_PMIND:
4382                         x86_sse_alu_sse41_reg_reg (code, X86_SSE_PMINSD, ins->sreg1, ins->sreg2);
4383                         break;
4384
4385                 case OP_PCMPEQB:
4386                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PCMPEQB, ins->sreg1, ins->sreg2);
4387                         break;
4388                 case OP_PCMPEQW:
4389                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PCMPEQW, ins->sreg1, ins->sreg2);
4390                         break;
4391                 case OP_PCMPEQD:
4392                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PCMPEQD, ins->sreg1, ins->sreg2);
4393                         break;
4394                 case OP_PCMPEQQ:
4395                         x86_sse_alu_sse41_reg_reg (code, X86_SSE_PCMPEQQ, ins->sreg1, ins->sreg2);
4396                         break;
4397
4398                 case OP_PCMPGTB:
4399                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PCMPGTB, ins->sreg1, ins->sreg2);
4400                         break;
4401                 case OP_PCMPGTW:
4402                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PCMPGTW, ins->sreg1, ins->sreg2);
4403                         break;
4404                 case OP_PCMPGTD:
4405                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PCMPGTD, ins->sreg1, ins->sreg2);
4406                         break;
4407                 case OP_PCMPGTQ:
4408                         x86_sse_alu_sse41_reg_reg (code, X86_SSE_PCMPGTQ, ins->sreg1, ins->sreg2);
4409                         break;
4410
4411                 case OP_PSUM_ABS_DIFF:
4412                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PSADBW, ins->sreg1, ins->sreg2);
4413                         break;
4414
4415                 case OP_UNPACK_LOWB:
4416                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PUNPCKLBW, ins->sreg1, ins->sreg2);
4417                         break;
4418                 case OP_UNPACK_LOWW:
4419                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PUNPCKLWD, ins->sreg1, ins->sreg2);
4420                         break;
4421                 case OP_UNPACK_LOWD:
4422                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PUNPCKLDQ, ins->sreg1, ins->sreg2);
4423                         break;
4424                 case OP_UNPACK_LOWQ:
4425                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PUNPCKLQDQ, ins->sreg1, ins->sreg2);
4426                         break;
4427                 case OP_UNPACK_LOWPS:
4428                         x86_sse_alu_ps_reg_reg (code, X86_SSE_UNPCKL, ins->sreg1, ins->sreg2);
4429                         break;
4430                 case OP_UNPACK_LOWPD:
4431                         x86_sse_alu_pd_reg_reg (code, X86_SSE_UNPCKL, ins->sreg1, ins->sreg2);
4432                         break;
4433
4434                 case OP_UNPACK_HIGHB:
4435                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PUNPCKHBW, ins->sreg1, ins->sreg2);
4436                         break;
4437                 case OP_UNPACK_HIGHW:
4438                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PUNPCKHWD, ins->sreg1, ins->sreg2);
4439                         break;
4440                 case OP_UNPACK_HIGHD:
4441                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PUNPCKHDQ, ins->sreg1, ins->sreg2);
4442                         break;
4443                 case OP_UNPACK_HIGHQ:
4444                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PUNPCKHQDQ, ins->sreg1, ins->sreg2);
4445                         break;
4446                 case OP_UNPACK_HIGHPS:
4447                         x86_sse_alu_ps_reg_reg (code, X86_SSE_UNPCKH, ins->sreg1, ins->sreg2);
4448                         break;
4449                 case OP_UNPACK_HIGHPD:
4450                         x86_sse_alu_pd_reg_reg (code, X86_SSE_UNPCKH, ins->sreg1, ins->sreg2);
4451                         break;
4452
4453                 case OP_PACKW:
4454                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PACKSSWB, ins->sreg1, ins->sreg2);
4455                         break;
4456                 case OP_PACKD:
4457                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PACKSSDW, ins->sreg1, ins->sreg2);
4458                         break;
4459                 case OP_PACKW_UN:
4460                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PACKUSWB, ins->sreg1, ins->sreg2);
4461                         break;
4462                 case OP_PACKD_UN:
4463                         x86_sse_alu_sse41_reg_reg (code, X86_SSE_PACKUSDW, ins->sreg1, ins->sreg2);
4464                         break;
4465
4466                 case OP_PADDB_SAT_UN:
4467                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PADDUSB, ins->sreg1, ins->sreg2);
4468                         break;
4469                 case OP_PSUBB_SAT_UN:
4470                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PSUBUSB, ins->sreg1, ins->sreg2);
4471                         break;
4472                 case OP_PADDW_SAT_UN:
4473                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PADDUSW, ins->sreg1, ins->sreg2);
4474                         break;
4475                 case OP_PSUBW_SAT_UN:
4476                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PSUBUSW, ins->sreg1, ins->sreg2);
4477                         break;
4478
4479                 case OP_PADDB_SAT:
4480                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PADDSB, ins->sreg1, ins->sreg2);
4481                         break;
4482                 case OP_PSUBB_SAT:
4483                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PSUBSB, ins->sreg1, ins->sreg2);
4484                         break;
4485                 case OP_PADDW_SAT:
4486                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PADDSW, ins->sreg1, ins->sreg2);
4487                         break;
4488                 case OP_PSUBW_SAT:
4489                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PSUBSW, ins->sreg1, ins->sreg2);
4490                         break;
4491                         
4492                 case OP_PMULW:
4493                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PMULLW, ins->sreg1, ins->sreg2);
4494                         break;
4495                 case OP_PMULD:
4496                         x86_sse_alu_sse41_reg_reg (code, X86_SSE_PMULLD, ins->sreg1, ins->sreg2);
4497                         break;
4498                 case OP_PMULQ:
4499                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PMULUDQ, ins->sreg1, ins->sreg2);
4500                         break;
4501                 case OP_PMULW_HIGH_UN:
4502                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PMULHUW, ins->sreg1, ins->sreg2);
4503                         break;
4504                 case OP_PMULW_HIGH:
4505                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PMULHW, ins->sreg1, ins->sreg2);
4506                         break;
4507
4508                 case OP_PSHRW:
4509                         x86_sse_shift_reg_imm (code, X86_SSE_PSHIFTW, X86_SSE_SHR, ins->dreg, ins->inst_imm);
4510                         break;
4511                 case OP_PSHRW_REG:
4512                         x86_sse_shift_reg_reg (code, X86_SSE_PSRLW_REG, ins->dreg, ins->sreg2);
4513                         break;
4514
4515                 case OP_PSARW:
4516                         x86_sse_shift_reg_imm (code, X86_SSE_PSHIFTW, X86_SSE_SAR, ins->dreg, ins->inst_imm);
4517                         break;
4518                 case OP_PSARW_REG:
4519                         x86_sse_shift_reg_reg (code, X86_SSE_PSRAW_REG, ins->dreg, ins->sreg2);
4520                         break;
4521
4522                 case OP_PSHLW:
4523                         x86_sse_shift_reg_imm (code, X86_SSE_PSHIFTW, X86_SSE_SHL, ins->dreg, ins->inst_imm);
4524                         break;
4525                 case OP_PSHLW_REG:
4526                         x86_sse_shift_reg_reg (code, X86_SSE_PSLLW_REG, ins->dreg, ins->sreg2);
4527                         break;
4528
4529                 case OP_PSHRD:
4530                         x86_sse_shift_reg_imm (code, X86_SSE_PSHIFTD, X86_SSE_SHR, ins->dreg, ins->inst_imm);
4531                         break;
4532                 case OP_PSHRD_REG:
4533                         x86_sse_shift_reg_reg (code, X86_SSE_PSRLD_REG, ins->dreg, ins->sreg2);
4534                         break;
4535
4536                 case OP_PSARD:
4537                         x86_sse_shift_reg_imm (code, X86_SSE_PSHIFTD, X86_SSE_SAR, ins->dreg, ins->inst_imm);
4538                         break;
4539                 case OP_PSARD_REG:
4540                         x86_sse_shift_reg_reg (code, X86_SSE_PSRAD_REG, ins->dreg, ins->sreg2);
4541                         break;
4542
4543                 case OP_PSHLD:
4544                         x86_sse_shift_reg_imm (code, X86_SSE_PSHIFTD, X86_SSE_SHL, ins->dreg, ins->inst_imm);
4545                         break;
4546                 case OP_PSHLD_REG:
4547                         x86_sse_shift_reg_reg (code, X86_SSE_PSLLD_REG, ins->dreg, ins->sreg2);
4548                         break;
4549
4550                 case OP_PSHRQ:
4551                         x86_sse_shift_reg_imm (code, X86_SSE_PSHIFTQ, X86_SSE_SHR, ins->dreg, ins->inst_imm);
4552                         break;
4553                 case OP_PSHRQ_REG:
4554                         x86_sse_shift_reg_reg (code, X86_SSE_PSRLQ_REG, ins->dreg, ins->sreg2);
4555                         break;
4556
4557                 case OP_PSHLQ:
4558                         x86_sse_shift_reg_imm (code, X86_SSE_PSHIFTQ, X86_SSE_SHL, ins->dreg, ins->inst_imm);
4559                         break;
4560                 case OP_PSHLQ_REG:
4561                         x86_sse_shift_reg_reg (code, X86_SSE_PSLLQ_REG, ins->dreg, ins->sreg2);
4562                         break;          
4563                         
4564                 case OP_ICONV_TO_X:
4565                         x86_movd_xreg_reg (code, ins->dreg, ins->sreg1);
4566                         break;
4567                 case OP_EXTRACT_I4:
4568                         x86_movd_reg_xreg (code, ins->dreg, ins->sreg1);
4569                         break;
4570                 case OP_EXTRACT_I1:
4571                 case OP_EXTRACT_U1:
4572                         x86_movd_reg_xreg (code, ins->dreg, ins->sreg1);
4573                         if (ins->inst_c0)
4574                                 x86_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
4575                         x86_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
4576                         break;
4577                 case OP_EXTRACT_I2:
4578                 case OP_EXTRACT_U2:
4579                         x86_movd_reg_xreg (code, ins->dreg, ins->sreg1);
4580                         if (ins->inst_c0)
4581                                 x86_shift_reg_imm (code, X86_SHR, ins->dreg, 16);
4582                         x86_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE);
4583                         break;
4584                 case OP_EXTRACT_R8:
4585                         if (ins->inst_c0)
4586                                 x86_sse_alu_pd_membase_reg (code, X86_SSE_MOVHPD_MEMBASE_REG, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset, ins->sreg1);
4587                         else
4588                                 x86_sse_alu_sd_membase_reg (code, X86_SSE_MOVSD_MEMBASE_REG, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset, ins->sreg1);
4589                         x86_fld_membase (code, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset, TRUE);
4590                         break;
4591
4592                 case OP_INSERT_I2:
4593                         x86_sse_alu_pd_reg_reg_imm (code, X86_SSE_PINSRW, ins->sreg1, ins->sreg2, ins->inst_c0);
4594                         break;
4595                 case OP_EXTRACTX_U2:
4596                         x86_sse_alu_pd_reg_reg_imm (code, X86_SSE_PEXTRW, ins->dreg, ins->sreg1, ins->inst_c0);
4597                         break;
4598                 case OP_INSERTX_U1_SLOW:
4599                         /*sreg1 is the extracted ireg (scratch)
4600                         /sreg2 is the to be inserted ireg (scratch)
4601                         /dreg is the xreg to receive the value*/
4602
4603                         /*clear the bits from the extracted word*/
4604                         x86_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
4605                         /*shift the value to insert if needed*/
4606                         if (ins->inst_c0 & 1)
4607                                 x86_shift_reg_imm (code, X86_SHL, ins->sreg2, 8);
4608                         /*join them together*/
4609                         x86_alu_reg_reg (code, X86_OR, ins->sreg1, ins->sreg2);
4610                         x86_sse_alu_pd_reg_reg_imm (code, X86_SSE_PINSRW, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
4611                         break;
4612                 case OP_INSERTX_I4_SLOW:
4613                         x86_sse_alu_pd_reg_reg_imm (code, X86_SSE_PINSRW, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
4614                         x86_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
4615                         x86_sse_alu_pd_reg_reg_imm (code, X86_SSE_PINSRW, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
4616                         break;
4617
4618                 case OP_INSERTX_R4_SLOW:
4619                         x86_fst_membase (code, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset, FALSE, TRUE);
4620                         /*TODO if inst_c0 == 0 use movss*/
4621                         x86_sse_alu_pd_reg_membase_imm (code, X86_SSE_PINSRW, ins->dreg, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset + 0, ins->inst_c0 * 2);
4622                         x86_sse_alu_pd_reg_membase_imm (code, X86_SSE_PINSRW, ins->dreg, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset + 2, ins->inst_c0 * 2 + 1);
4623                         break;
4624                 case OP_INSERTX_R8_SLOW:
4625                         x86_fst_membase (code, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset, TRUE, TRUE);
4626                         if (ins->inst_c0)
4627                                 x86_sse_alu_pd_reg_membase (code, X86_SSE_MOVHPD_REG_MEMBASE, ins->dreg, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset);
4628                         else
4629                                 x86_sse_alu_pd_reg_membase (code, X86_SSE_MOVSD_REG_MEMBASE, ins->dreg, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset);
4630                         break;
4631
4632                 case OP_STOREX_MEMBASE_REG:
4633                 case OP_STOREX_MEMBASE:
4634                         x86_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
4635                         break;
4636                 case OP_LOADX_MEMBASE:
4637                         x86_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
4638                         break;
4639                 case OP_LOADX_ALIGNED_MEMBASE:
4640                         x86_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
4641                         break;
4642                 case OP_STOREX_ALIGNED_MEMBASE_REG:
4643                         x86_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
4644                         break;
4645                 case OP_STOREX_NTA_MEMBASE_REG:
4646                         x86_sse_alu_reg_membase (code, X86_SSE_MOVNTPS, ins->dreg, ins->sreg1, ins->inst_offset);
4647                         break;
4648                 case OP_PREFETCH_MEMBASE:
4649                         x86_sse_alu_reg_membase (code, X86_SSE_PREFETCH, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
4650
4651                         break;
4652                 case OP_XMOVE:
4653                         /*FIXME the peephole pass should have killed this*/
4654                         if (ins->dreg != ins->sreg1)
4655                                 x86_movaps_reg_reg (code, ins->dreg, ins->sreg1);
4656                         break;          
4657                 case OP_XZERO:
4658                         x86_sse_alu_pd_reg_reg (code, X86_SSE_PXOR, ins->dreg, ins->dreg);
4659                         break;
4660                 case OP_ICONV_TO_R8_RAW:
4661                         x86_mov_membase_reg (code, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset, ins->sreg1, 4);
4662                         x86_fld_membase (code, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset, FALSE);
4663                         break;
4664
4665                 case OP_FCONV_TO_R8_X:
4666                         x86_fst_membase (code, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset, TRUE, TRUE);
4667                         x86_movsd_reg_membase (code, ins->dreg, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset);
4668                         break;
4669
4670                 case OP_XCONV_R8_TO_I4:
4671                         x86_cvttsd2si (code, ins->dreg, ins->sreg1);
4672                         switch (ins->backend.source_opcode) {
4673                         case OP_FCONV_TO_I1:
4674                                 x86_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
4675                                 break;
4676                         case OP_FCONV_TO_U1:
4677                                 x86_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
4678                                 break;
4679                         case OP_FCONV_TO_I2:
4680                                 x86_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
4681                                 break;
4682                         case OP_FCONV_TO_U2:
4683                                 x86_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
4684                                 break;
4685                         }                       
4686                         break;
4687
4688                 case OP_EXPAND_I1:
4689                         /*FIXME this causes a partial register stall, maybe it would not be that bad to use shift + mask + or*/
4690                         /*The +4 is to get a mov ?h, ?l over the same reg.*/
4691                         x86_mov_reg_reg (code, ins->dreg + 4, ins->dreg, 1);
4692                         x86_sse_alu_pd_reg_reg_imm (code, X86_SSE_PINSRW, ins->dreg, ins->sreg1, 0);
4693                         x86_sse_alu_pd_reg_reg_imm (code, X86_SSE_PINSRW, ins->dreg, ins->sreg1, 1);
4694                         x86_sse_shift_reg_imm (code, X86_SSE_PSHUFD, ins->dreg, ins->dreg, 0);
4695                         break;
4696                 case OP_EXPAND_I2:
4697                         x86_sse_alu_pd_reg_reg_imm (code, X86_SSE_PINSRW, ins->dreg, ins->sreg1, 0);
4698                         x86_sse_alu_pd_reg_reg_imm (code, X86_SSE_PINSRW, ins->dreg, ins->sreg1, 1);
4699                         x86_sse_shift_reg_imm (code, X86_SSE_PSHUFD, ins->dreg, ins->dreg, 0);
4700                         break;
4701                 case OP_EXPAND_I4:
4702                         x86_movd_xreg_reg (code, ins->dreg, ins->sreg1);
4703                         x86_sse_shift_reg_imm (code, X86_SSE_PSHUFD, ins->dreg, ins->dreg, 0);
4704                         break;
4705                 case OP_EXPAND_R4:
4706                         x86_fst_membase (code, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset, FALSE, TRUE);
4707                         x86_movd_xreg_membase (code, ins->dreg, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset);
4708                         x86_sse_shift_reg_imm (code, X86_SSE_PSHUFD, ins->dreg, ins->dreg, 0);
4709                         break;
4710                 case OP_EXPAND_R8:
4711                         x86_fst_membase (code, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset, TRUE, TRUE);
4712                         x86_movsd_reg_membase (code, ins->dreg, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset);
4713                         x86_sse_shift_reg_imm (code, X86_SSE_PSHUFD, ins->dreg, ins->dreg, 0x44);
4714                         break;
4715
4716                 case OP_CVTDQ2PD:
4717                         x86_sse_alu_ss_reg_reg (code, X86_SSE_CVTDQ2PD, ins->dreg, ins->sreg1);
4718                         break;
4719                 case OP_CVTDQ2PS:
4720                         x86_sse_alu_ps_reg_reg (code, X86_SSE_CVTDQ2PS, ins->dreg, ins->sreg1);
4721                         break;
4722                 case OP_CVTPD2DQ:
4723                         x86_sse_alu_sd_reg_reg (code, X86_SSE_CVTPD2DQ, ins->dreg, ins->sreg1);
4724                         break;
4725                 case OP_CVTPD2PS:
4726                         x86_sse_alu_pd_reg_reg (code, X86_SSE_CVTPD2PS, ins->dreg, ins->sreg1);
4727                         break;
4728                 case OP_CVTPS2DQ:
4729                         x86_sse_alu_pd_reg_reg (code, X86_SSE_CVTPS2DQ, ins->dreg, ins->sreg1);
4730                         break;
4731                 case OP_CVTPS2PD:
4732                         x86_sse_alu_ps_reg_reg (code, X86_SSE_CVTPS2PD, ins->dreg, ins->sreg1);
4733                         break;
4734                 case OP_CVTTPD2DQ:
4735                         x86_sse_alu_pd_reg_reg (code, X86_SSE_CVTTPD2DQ, ins->dreg, ins->sreg1);
4736                         break;
4737                 case OP_CVTTPS2DQ:
4738                         x86_sse_alu_ss_reg_reg (code, X86_SSE_CVTTPS2DQ, ins->dreg, ins->sreg1);
4739                         break;
4740
4741 #endif
4742                 case OP_LIVERANGE_START: {
4743                         if (cfg->verbose_level > 1)
4744                                 printf ("R%d START=0x%x\n", MONO_VARINFO (cfg, ins->inst_c0)->vreg, (int)(code - cfg->native_code));
4745                         MONO_VARINFO (cfg, ins->inst_c0)->live_range_start = code - cfg->native_code;
4746                         break;
4747                 }
4748                 case OP_LIVERANGE_END: {
4749                         if (cfg->verbose_level > 1)
4750                                 printf ("R%d END=0x%x\n", MONO_VARINFO (cfg, ins->inst_c0)->vreg, (int)(code - cfg->native_code));
4751                         MONO_VARINFO (cfg, ins->inst_c0)->live_range_end = code - cfg->native_code;
4752                         break;
4753                 }
4754                 case OP_NACL_GC_SAFE_POINT: {
4755 #if defined(__native_client_codegen__)
4756                         code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, (gpointer)mono_nacl_gc);
4757 #endif
4758                         break;
4759                 }
4760                 case OP_GC_LIVENESS_DEF:
4761                 case OP_GC_LIVENESS_USE:
4762                 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4763                         ins->backend.pc_offset = code - cfg->native_code;
4764                         break;
4765                 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4766                         ins->backend.pc_offset = code - cfg->native_code;
4767                         bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4768                         break;
4769                 default:
4770                         g_warning ("unknown opcode %s\n", mono_inst_name (ins->opcode));
4771                         g_assert_not_reached ();
4772                 }
4773
4774                 if (G_UNLIKELY ((code - cfg->native_code - offset) > max_len)) {
4775 #ifndef __native_client_codegen__
4776                         g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %d)",
4777                                            mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
4778                         g_assert_not_reached ();
4779 #endif  /* __native_client_codegen__ */
4780                 }
4781                
4782                 cpos += max_len;
4783         }
4784
4785         cfg->code_len = code - cfg->native_code;
4786 }
4787
4788 #endif /* DISABLE_JIT */
4789
4790 void
4791 mono_arch_register_lowlevel_calls (void)
4792 {
4793 }
4794
4795 void
4796 mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, MonoCodeManager *dyn_code_mp, gboolean run_cctors)
4797 {
4798         MonoJumpInfo *patch_info;
4799         gboolean compile_aot = !run_cctors;
4800
4801         for (patch_info = ji; patch_info; patch_info = patch_info->next) {
4802                 unsigned char *ip = patch_info->ip.i + code;
4803                 const unsigned char *target;
4804
4805                 target = mono_resolve_patch_target (method, domain, code, patch_info, run_cctors);
4806
4807                 if (compile_aot) {
4808                         switch (patch_info->type) {
4809                         case MONO_PATCH_INFO_BB:
4810                         case MONO_PATCH_INFO_LABEL:
4811                                 break;
4812                         default:
4813                                 /* No need to patch these */
4814                                 continue;
4815                         }
4816                 }
4817
4818                 switch (patch_info->type) {
4819                 case MONO_PATCH_INFO_IP:
4820                         *((gconstpointer *)(ip)) = target;
4821                         break;
4822                 case MONO_PATCH_INFO_CLASS_INIT: {
4823                         guint8 *code = ip;
4824                         /* Might already been changed to a nop */
4825                         x86_call_code (code, 0);
4826                         x86_patch (ip, target);
4827                         break;
4828                 }
4829                 case MONO_PATCH_INFO_ABS:
4830                 case MONO_PATCH_INFO_METHOD:
4831                 case MONO_PATCH_INFO_METHOD_JUMP:
4832                 case MONO_PATCH_INFO_INTERNAL_METHOD:
4833                 case MONO_PATCH_INFO_BB:
4834                 case MONO_PATCH_INFO_LABEL:
4835                 case MONO_PATCH_INFO_RGCTX_FETCH:
4836                 case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
4837                 case MONO_PATCH_INFO_MONITOR_ENTER:
4838                 case MONO_PATCH_INFO_MONITOR_EXIT:
4839 #if defined(__native_client_codegen__) && defined(__native_client__)
4840                         if (nacl_is_code_address (code)) {
4841                                 /* For tail calls, code is patched after being installed */
4842                                 /* but not through the normal "patch callsite" method.   */
4843                                 unsigned char buf[kNaClAlignment];
4844                                 unsigned char *aligned_code = (uintptr_t)code & ~kNaClAlignmentMask;
4845                                 unsigned char *_target = target;
4846                                 int ret;
4847                                 /* All patch targets modified in x86_patch */
4848                                 /* are IP relative.                        */
4849                                 _target = _target + (uintptr_t)buf - (uintptr_t)aligned_code;
4850                                 memcpy (buf, aligned_code, kNaClAlignment);
4851                                 /* Patch a temp buffer of bundle size, */
4852                                 /* then install to actual location.    */
4853                                 x86_patch (buf + ((uintptr_t)code - (uintptr_t)aligned_code), _target);
4854                                 ret = nacl_dyncode_modify (aligned_code, buf, kNaClAlignment);
4855                                 g_assert (ret == 0);
4856                         }
4857                         else {
4858                                 x86_patch (ip, target);
4859                         }
4860 #else
4861                         x86_patch (ip, target);
4862 #endif
4863                         break;
4864                 case MONO_PATCH_INFO_NONE:
4865                         break;
4866                 case MONO_PATCH_INFO_R4:
4867                 case MONO_PATCH_INFO_R8: {
4868                         guint32 offset = mono_arch_get_patch_offset (ip);
4869                         *((gconstpointer *)(ip + offset)) = target;
4870                         break;
4871                 }
4872                 default: {
4873                         guint32 offset = mono_arch_get_patch_offset (ip);
4874 #if !defined(__native_client__)
4875                         *((gconstpointer *)(ip + offset)) = target;
4876 #else
4877                         *((gconstpointer *)(ip + offset)) = nacl_modify_patch_target (target);
4878 #endif
4879                         break;
4880                 }
4881                 }
4882         }
4883 }
4884
4885 guint8 *
4886 mono_arch_emit_prolog (MonoCompile *cfg)
4887 {
4888         MonoMethod *method = cfg->method;
4889         MonoBasicBlock *bb;
4890         MonoMethodSignature *sig;
4891         MonoInst *inst;
4892         int alloc_size, pos, max_offset, i, cfa_offset;
4893         guint8 *code;
4894         gboolean need_stack_frame;
4895 #ifdef __native_client_codegen__
4896         guint alignment_check;
4897 #endif
4898
4899         cfg->code_size = MAX (cfg->header->code_size * 4, 10240);
4900
4901         if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
4902                 cfg->code_size += 512;
4903
4904 #if defined(__default_codegen__)
4905         code = cfg->native_code = g_malloc (cfg->code_size);
4906 #elif defined(__native_client_codegen__)
4907         /* native_code_alloc is not 32-byte aligned, native_code is. */
4908         cfg->native_code_alloc = g_malloc (cfg->code_size + kNaClAlignment);
4909
4910         /* Align native_code to next nearest kNaclAlignment byte. */
4911         cfg->native_code = (guint)cfg->native_code_alloc + kNaClAlignment; 
4912         cfg->native_code = (guint)cfg->native_code & ~kNaClAlignmentMask;
4913         
4914         code = cfg->native_code;
4915
4916         alignment_check = (guint)cfg->native_code & kNaClAlignmentMask;
4917         g_assert(alignment_check == 0);
4918 #endif
4919
4920         /* Offset between RSP and the CFA */
4921         cfa_offset = 0;
4922
4923         // CFA = sp + 4
4924         cfa_offset = sizeof (gpointer);
4925         mono_emit_unwind_op_def_cfa (cfg, code, X86_ESP, sizeof (gpointer));
4926         // IP saved at CFA - 4
4927         /* There is no IP reg on x86 */
4928         mono_emit_unwind_op_offset (cfg, code, X86_NREG, -cfa_offset);
4929
4930         need_stack_frame = needs_stack_frame (cfg);
4931
4932         if (need_stack_frame) {
4933                 x86_push_reg (code, X86_EBP);
4934                 cfa_offset += sizeof (gpointer);
4935                 mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
4936                 mono_emit_unwind_op_offset (cfg, code, X86_EBP, - cfa_offset);
4937                 x86_mov_reg_reg (code, X86_EBP, X86_ESP, 4);
4938                 mono_emit_unwind_op_def_cfa_reg (cfg, code, X86_EBP);
4939         } else {
4940                 cfg->frame_reg = X86_ESP;
4941         }
4942
4943         alloc_size = cfg->stack_offset;
4944         pos = 0;
4945
4946         if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
4947                 /* Might need to attach the thread to the JIT  or change the domain for the callback */
4948                 if (appdomain_tls_offset != -1 && lmf_tls_offset != -1) {
4949                         guint8 *buf, *no_domain_branch;
4950
4951                         code = mono_x86_emit_tls_get (code, X86_EAX, appdomain_tls_offset);
4952                         x86_alu_reg_imm (code, X86_CMP, X86_EAX, GPOINTER_TO_UINT (cfg->domain));
4953                         no_domain_branch = code;
4954                         x86_branch8 (code, X86_CC_NE, 0, 0);
4955                         code = mono_x86_emit_tls_get ( code, X86_EAX, lmf_tls_offset);
4956                         x86_test_reg_reg (code, X86_EAX, X86_EAX);
4957                         buf = code;
4958                         x86_branch8 (code, X86_CC_NE, 0, 0);
4959                         x86_patch (no_domain_branch, code);
4960                         x86_push_imm (code, cfg->domain);
4961                         code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_jit_thread_attach");
4962                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
4963                         x86_patch (buf, code);
4964 #ifdef TARGET_WIN32
4965                         /* The TLS key actually contains a pointer to the MonoJitTlsData structure */
4966                         /* FIXME: Add a separate key for LMF to avoid this */
4967                         x86_alu_reg_imm (code, X86_ADD, X86_EAX, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
4968 #endif
4969                 }
4970                 else {
4971                         if (cfg->compile_aot) {
4972                                 /* 
4973                                  * This goes before the saving of callee saved regs, so save the got reg
4974                                  * ourselves.
4975                                  */
4976                                 x86_push_reg (code, MONO_ARCH_GOT_REG);
4977                                 code = mono_arch_emit_load_got_addr (cfg->native_code, code, cfg, NULL);
4978                                 x86_push_imm (code, 0);
4979                         } else {
4980                                 x86_push_imm (code, cfg->domain);
4981                         }
4982                         code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_jit_thread_attach");
4983                         x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
4984                         if (cfg->compile_aot)
4985                                 x86_pop_reg (code, MONO_ARCH_GOT_REG);
4986                 }
4987         }
4988
4989         if (method->save_lmf) {
4990                 pos += sizeof (MonoLMF);
4991
4992                 /* save the current IP */
4993                 if (cfg->compile_aot) {
4994                         /* This pushes the current ip */
4995                         x86_call_imm (code, 0);
4996                 } else {
4997                         mono_add_patch_info (cfg, code + 1 - cfg->native_code, MONO_PATCH_INFO_IP, NULL);
4998                         x86_push_imm_template (code);
4999                 }
5000                 cfa_offset += sizeof (gpointer);
5001
5002                 /* save all caller saved regs */
5003                 x86_push_reg (code, X86_EBP);
5004                 cfa_offset += sizeof (gpointer);
5005                 x86_push_reg (code, X86_ESI);
5006                 cfa_offset += sizeof (gpointer);
5007                 mono_emit_unwind_op_offset (cfg, code, X86_ESI, - cfa_offset);
5008                 x86_push_reg (code, X86_EDI);
5009                 cfa_offset += sizeof (gpointer);
5010                 mono_emit_unwind_op_offset (cfg, code, X86_EDI, - cfa_offset);
5011                 x86_push_reg (code, X86_EBX);
5012                 cfa_offset += sizeof (gpointer);
5013                 mono_emit_unwind_op_offset (cfg, code, X86_EBX, - cfa_offset);
5014
5015                 if ((lmf_tls_offset != -1) && !is_win32 && !optimize_for_xen) {
5016                         /*
5017                          * Optimized version which uses the mono_lmf TLS variable instead of indirection
5018                          * through the mono_lmf_addr TLS variable.
5019                          */
5020                         /* %eax = previous_lmf */
5021                         x86_prefix (code, X86_GS_PREFIX);
5022                         x86_mov_reg_mem (code, X86_EAX, lmf_tls_offset, 4);
5023                         /* skip esp + method_info + lmf */
5024                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, 12);
5025                         /* push previous_lmf */
5026                         x86_push_reg (code, X86_EAX);
5027                         /* new lmf = ESP */
5028                         x86_prefix (code, X86_GS_PREFIX);
5029                         x86_mov_mem_reg (code, lmf_tls_offset, X86_ESP, 4);
5030                 } else {
5031                         /* get the address of lmf for the current thread */
5032                         /* 
5033                          * This is performance critical so we try to use some tricks to make
5034                          * it fast.
5035                          */                                                                        
5036
5037                         if (lmf_addr_tls_offset != -1) {
5038                                 /* Load lmf quicky using the GS register */
5039                                 code = mono_x86_emit_tls_get (code, X86_EAX, lmf_addr_tls_offset);
5040 #ifdef TARGET_WIN32
5041                                 /* The TLS key actually contains a pointer to the MonoJitTlsData structure */
5042                                 /* FIXME: Add a separate key for LMF to avoid this */
5043                                 x86_alu_reg_imm (code, X86_ADD, X86_EAX, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
5044 #endif
5045                         } else {
5046                                 if (cfg->compile_aot)
5047                                         code = mono_arch_emit_load_got_addr (cfg->native_code, code, cfg, NULL);
5048                                 code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_get_lmf_addr");
5049                         }
5050
5051                         /* Skip esp + method info */
5052                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, 8);
5053
5054                         /* push lmf */
5055                         x86_push_reg (code, X86_EAX); 
5056                         /* push *lfm (previous_lmf) */
5057                         x86_push_membase (code, X86_EAX, 0);
5058                         /* *(lmf) = ESP */
5059                         x86_mov_membase_reg (code, X86_EAX, 0, X86_ESP, 4);
5060                 }
5061         } else {
5062
5063                 if (cfg->used_int_regs & (1 << X86_EBX)) {
5064                         x86_push_reg (code, X86_EBX);
5065                         pos += 4;
5066                         cfa_offset += sizeof (gpointer);
5067                         mono_emit_unwind_op_offset (cfg, code, X86_EBX, - cfa_offset);
5068                 }
5069
5070                 if (cfg->used_int_regs & (1 << X86_EDI)) {
5071                         x86_push_reg (code, X86_EDI);
5072                         pos += 4;
5073                         cfa_offset += sizeof (gpointer);
5074                         mono_emit_unwind_op_offset (cfg, code, X86_EDI, - cfa_offset);
5075                 }
5076
5077                 if (cfg->used_int_regs & (1 << X86_ESI)) {
5078                         x86_push_reg (code, X86_ESI);
5079                         pos += 4;
5080                         cfa_offset += sizeof (gpointer);
5081                         mono_emit_unwind_op_offset (cfg, code, X86_ESI, - cfa_offset);
5082                 }
5083         }
5084
5085         alloc_size -= pos;
5086
5087         /* the original alloc_size is already aligned: there is %ebp and retip pushed, so realign */
5088         if (mono_do_x86_stack_align && need_stack_frame) {
5089                 int tot = alloc_size + pos + 4; /* ret ip */
5090                 if (need_stack_frame)
5091                         tot += 4; /* ebp */
5092                 tot &= MONO_ARCH_FRAME_ALIGNMENT - 1;
5093                 if (tot)
5094                         alloc_size += MONO_ARCH_FRAME_ALIGNMENT - tot;
5095         }
5096
5097         if (alloc_size) {
5098                 /* See mono_emit_stack_alloc */
5099 #if defined(TARGET_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK)
5100                 guint32 remaining_size = alloc_size;
5101                 /*FIXME handle unbounded code expansion, we should use a loop in case of more than X interactions*/
5102                 guint32 required_code_size = ((remaining_size / 0x1000) + 1) * 8; /*8 is the max size of x86_alu_reg_imm + x86_test_membase_reg*/
5103                 guint32 offset = code - cfg->native_code;
5104                 if (G_UNLIKELY (required_code_size >= (cfg->code_size - offset))) {
5105                         while (required_code_size >= (cfg->code_size - offset))
5106                                 cfg->code_size *= 2;
5107                         cfg->native_code = mono_realloc_native_code(cfg);
5108                         code = cfg->native_code + offset;
5109                         mono_jit_stats.code_reallocs++;
5110                 }
5111                 while (remaining_size >= 0x1000) {
5112                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, 0x1000);
5113                         x86_test_membase_reg (code, X86_ESP, 0, X86_ESP);
5114                         remaining_size -= 0x1000;
5115                 }
5116                 if (remaining_size)
5117                         x86_alu_reg_imm (code, X86_SUB, X86_ESP, remaining_size);
5118 #else
5119                 x86_alu_reg_imm (code, X86_SUB, X86_ESP, alloc_size);
5120 #endif
5121
5122                 g_assert (need_stack_frame);
5123         }
5124
5125         if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED ||
5126                         cfg->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
5127                 x86_alu_reg_imm (code, X86_AND, X86_ESP, -MONO_ARCH_FRAME_ALIGNMENT);
5128         }
5129
5130 #if DEBUG_STACK_ALIGNMENT
5131         /* check the stack is aligned */
5132         if (need_stack_frame && method->wrapper_type == MONO_WRAPPER_NONE) {
5133                 x86_mov_reg_reg (code, X86_ECX, X86_ESP, 4);
5134                 x86_alu_reg_imm (code, X86_AND, X86_ECX, MONO_ARCH_FRAME_ALIGNMENT - 1);
5135                 x86_alu_reg_imm (code, X86_CMP, X86_ECX, 0);
5136                 x86_branch_disp (code, X86_CC_EQ, 3, FALSE);
5137                 x86_breakpoint (code);
5138         }
5139 #endif
5140
5141         /* compute max_offset in order to use short forward jumps */
5142         max_offset = 0;
5143         if (cfg->opt & MONO_OPT_BRANCH) {
5144                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5145                         MonoInst *ins;
5146                         bb->max_offset = max_offset;
5147
5148                         if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5149                                 max_offset += 6;
5150                         /* max alignment for loops */
5151                         if ((cfg->opt & MONO_OPT_LOOP) && bb_is_loop_start (bb))
5152                                 max_offset += LOOP_ALIGNMENT;
5153 #ifdef __native_client_codegen__
5154                         /* max alignment for native client */
5155                         max_offset += kNaClAlignment;
5156 #endif
5157                         MONO_BB_FOR_EACH_INS (bb, ins) {
5158                                 if (ins->opcode == OP_LABEL)
5159                                         ins->inst_c1 = max_offset;
5160 #ifdef __native_client_codegen__
5161                                 {
5162                                         int space_in_block = kNaClAlignment -
5163                                                 ((max_offset + cfg->code_len) & kNaClAlignmentMask);
5164                                         int max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5165                                         if (space_in_block < max_len && max_len < kNaClAlignment) {
5166                                                 max_offset += space_in_block;
5167                                         }
5168                                 }
5169 #endif  /* __native_client_codegen__ */
5170                                 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5171                         }
5172                 }
5173         }
5174
5175         /* store runtime generic context */
5176         if (cfg->rgctx_var) {
5177                 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET && cfg->rgctx_var->inst_basereg == X86_EBP);
5178
5179                 x86_mov_membase_reg (code, X86_EBP, cfg->rgctx_var->inst_offset, MONO_ARCH_RGCTX_REG, 4);
5180         }
5181
5182         if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
5183                 code = mono_arch_instrument_prolog (cfg, mono_trace_enter_method, code, TRUE);
5184
5185         /* load arguments allocated to register from the stack */
5186         sig = mono_method_signature (method);
5187         pos = 0;
5188
5189         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5190                 inst = cfg->args [pos];
5191                 if (inst->opcode == OP_REGVAR) {
5192                         g_assert (need_stack_frame);
5193                         x86_mov_reg_membase (code, inst->dreg, X86_EBP, inst->inst_offset, 4);
5194                         if (cfg->verbose_level > 2)
5195                                 g_print ("Argument %d assigned to register %s\n", pos, mono_arch_regname (inst->dreg));
5196                 }
5197                 pos++;
5198         }
5199
5200         cfg->code_len = code - cfg->native_code;
5201
5202         g_assert (cfg->code_len < cfg->code_size);
5203
5204         return code;
5205 }
5206
5207 void
5208 mono_arch_emit_epilog (MonoCompile *cfg)
5209 {
5210         MonoMethod *method = cfg->method;
5211         MonoMethodSignature *sig = mono_method_signature (method);
5212         int quad, pos;
5213         guint32 stack_to_pop;
5214         guint8 *code;
5215         int max_epilog_size = 16;
5216         CallInfo *cinfo;
5217         gboolean need_stack_frame = needs_stack_frame (cfg);
5218
5219         if (cfg->method->save_lmf)
5220                 max_epilog_size += 128;
5221
5222         while (cfg->code_len + max_epilog_size > (cfg->code_size - 16)) {
5223                 cfg->code_size *= 2;
5224                 cfg->native_code = mono_realloc_native_code(cfg);
5225                 mono_jit_stats.code_reallocs++;
5226         }
5227
5228         code = cfg->native_code + cfg->code_len;
5229
5230         if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
5231                 code = mono_arch_instrument_epilog (cfg, mono_trace_leave_method, code, TRUE);
5232
5233         /* the code restoring the registers must be kept in sync with OP_JMP */
5234         pos = 0;
5235         
5236         if (method->save_lmf) {
5237                 gint32 prev_lmf_reg;
5238                 gint32 lmf_offset = -sizeof (MonoLMF);
5239
5240                 /* check if we need to restore protection of the stack after a stack overflow */
5241                 if (mono_get_jit_tls_offset () != -1) {
5242                         guint8 *patch;
5243                         code = mono_x86_emit_tls_get (code, X86_ECX, mono_get_jit_tls_offset ());
5244                         /* we load the value in a separate instruction: this mechanism may be
5245                          * used later as a safer way to do thread interruption
5246                          */
5247                         x86_mov_reg_membase (code, X86_ECX, X86_ECX, G_STRUCT_OFFSET (MonoJitTlsData, restore_stack_prot), 4);
5248                         x86_alu_reg_imm (code, X86_CMP, X86_ECX, 0);
5249                         patch = code;
5250                         x86_branch8 (code, X86_CC_Z, 0, FALSE);
5251                         /* note that the call trampoline will preserve eax/edx */
5252                         x86_call_reg (code, X86_ECX);
5253                         x86_patch (patch, code);
5254                 } else {
5255                         /* FIXME: maybe save the jit tls in the prolog */
5256                 }
5257                 if ((lmf_tls_offset != -1) && !is_win32 && !optimize_for_xen) {
5258                         /*
5259                          * Optimized version which uses the mono_lmf TLS variable instead of indirection
5260                          * through the mono_lmf_addr TLS variable.
5261                          */
5262                         /* reg = previous_lmf */
5263                         x86_mov_reg_membase (code, X86_ECX, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), 4);
5264
5265                         /* lmf = previous_lmf */
5266                         x86_prefix (code, X86_GS_PREFIX);
5267                         x86_mov_mem_reg (code, lmf_tls_offset, X86_ECX, 4);
5268                 } else {
5269                         /* Find a spare register */
5270                         switch (mini_type_get_underlying_type (cfg->generic_sharing_context, sig->ret)->type) {
5271                         case MONO_TYPE_I8:
5272                         case MONO_TYPE_U8:
5273                                 prev_lmf_reg = X86_EDI;
5274                                 cfg->used_int_regs |= (1 << X86_EDI);
5275                                 break;
5276                         default:
5277                                 prev_lmf_reg = X86_EDX;
5278                                 break;
5279                         }
5280
5281                         /* reg = previous_lmf */
5282                         x86_mov_reg_membase (code, prev_lmf_reg, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), 4);
5283
5284                         /* ecx = lmf */
5285                         x86_mov_reg_membase (code, X86_ECX, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), 4);
5286
5287                         /* *(lmf) = previous_lmf */
5288                         x86_mov_membase_reg (code, X86_ECX, 0, prev_lmf_reg, 4);
5289                 }
5290
5291                 /* restore caller saved regs */
5292                 if (cfg->used_int_regs & (1 << X86_EBX)) {
5293                         x86_mov_reg_membase (code, X86_EBX, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebx), 4);
5294                 }
5295
5296                 if (cfg->used_int_regs & (1 << X86_EDI)) {
5297                         x86_mov_reg_membase (code, X86_EDI, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, edi), 4);
5298                 }
5299                 if (cfg->used_int_regs & (1 << X86_ESI)) {
5300                         x86_mov_reg_membase (code, X86_ESI, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, esi), 4);
5301                 }
5302
5303                 /* EBP is restored by LEAVE */
5304         } else {
5305                 if (cfg->used_int_regs & (1 << X86_EBX)) {
5306                         pos -= 4;
5307                 }
5308                 if (cfg->used_int_regs & (1 << X86_EDI)) {
5309                         pos -= 4;
5310                 }
5311                 if (cfg->used_int_regs & (1 << X86_ESI)) {
5312                         pos -= 4;
5313                 }
5314
5315                 if (pos) {
5316                         g_assert (need_stack_frame);
5317                         x86_lea_membase (code, X86_ESP, X86_EBP, pos);
5318                 }
5319
5320                 if (cfg->used_int_regs & (1 << X86_ESI)) {
5321                         x86_pop_reg (code, X86_ESI);
5322                 }
5323                 if (cfg->used_int_regs & (1 << X86_EDI)) {
5324                         x86_pop_reg (code, X86_EDI);
5325                 }
5326                 if (cfg->used_int_regs & (1 << X86_EBX)) {
5327                         x86_pop_reg (code, X86_EBX);
5328                 }
5329         }
5330
5331         /* Load returned vtypes into registers if needed */
5332         cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
5333         if (cinfo->ret.storage == ArgValuetypeInReg) {
5334                 for (quad = 0; quad < 2; quad ++) {
5335                         switch (cinfo->ret.pair_storage [quad]) {
5336                         case ArgInIReg:
5337                                 x86_mov_reg_membase (code, cinfo->ret.pair_regs [quad], cfg->ret->inst_basereg, cfg->ret->inst_offset + (quad * sizeof (gpointer)), 4);
5338                                 break;
5339                         case ArgOnFloatFpStack:
5340                                 x86_fld_membase (code, cfg->ret->inst_basereg, cfg->ret->inst_offset + (quad * sizeof (gpointer)), FALSE);
5341                                 break;
5342                         case ArgOnDoubleFpStack:
5343                                 x86_fld_membase (code, cfg->ret->inst_basereg, cfg->ret->inst_offset + (quad * sizeof (gpointer)), TRUE);
5344                                 break;
5345                         case ArgNone:
5346                                 break;
5347                         default:
5348                                 g_assert_not_reached ();
5349                         }
5350                 }
5351         }
5352
5353         if (need_stack_frame)
5354                 x86_leave (code);
5355
5356         if (CALLCONV_IS_STDCALL (sig)) {
5357                 MonoJitArgumentInfo *arg_info = alloca (sizeof (MonoJitArgumentInfo) * (sig->param_count + 1));
5358
5359                 stack_to_pop = mono_arch_get_argument_info (sig, sig->param_count, arg_info);
5360         } else if (MONO_TYPE_ISSTRUCT (mono_method_signature (cfg->method)->ret) && (cinfo->ret.storage == ArgOnStack))
5361                 stack_to_pop = 4;
5362         else
5363                 stack_to_pop = 0;
5364
5365         if (stack_to_pop) {
5366                 g_assert (need_stack_frame);
5367                 x86_ret_imm (code, stack_to_pop);
5368         } else {
5369                 x86_ret (code);
5370         }
5371
5372         cfg->code_len = code - cfg->native_code;
5373
5374         g_assert (cfg->code_len < cfg->code_size);
5375 }
5376
5377 void
5378 mono_arch_emit_exceptions (MonoCompile *cfg)
5379 {
5380         MonoJumpInfo *patch_info;
5381         int nthrows, i;
5382         guint8 *code;
5383         MonoClass *exc_classes [16];
5384         guint8 *exc_throw_start [16], *exc_throw_end [16];
5385         guint32 code_size;
5386         int exc_count = 0;
5387
5388         /* Compute needed space */
5389         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
5390                 if (patch_info->type == MONO_PATCH_INFO_EXC)
5391                         exc_count++;
5392         }
5393
5394         /* 
5395          * make sure we have enough space for exceptions
5396          * 16 is the size of two push_imm instructions and a call
5397          */
5398         if (cfg->compile_aot)
5399                 code_size = exc_count * 32;
5400         else
5401                 code_size = exc_count * 16;
5402
5403         while (cfg->code_len + code_size > (cfg->code_size - 16)) {
5404                 cfg->code_size *= 2;
5405                 cfg->native_code = mono_realloc_native_code(cfg);
5406                 mono_jit_stats.code_reallocs++;
5407         }
5408
5409         code = cfg->native_code + cfg->code_len;
5410
5411         nthrows = 0;
5412         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
5413                 switch (patch_info->type) {
5414                 case MONO_PATCH_INFO_EXC: {
5415                         MonoClass *exc_class;
5416                         guint8 *buf, *buf2;
5417                         guint32 throw_ip;
5418
5419                         x86_patch (patch_info->ip.i + cfg->native_code, code);
5420
5421                         exc_class = mono_class_from_name (mono_defaults.corlib, "System", patch_info->data.name);
5422                         g_assert (exc_class);
5423                         throw_ip = patch_info->ip.i;
5424
5425                         /* Find a throw sequence for the same exception class */
5426                         for (i = 0; i < nthrows; ++i)
5427                                 if (exc_classes [i] == exc_class)
5428                                         break;
5429                         if (i < nthrows) {
5430                                 x86_push_imm (code, (exc_throw_end [i] - cfg->native_code) - throw_ip);
5431                                 x86_jump_code (code, exc_throw_start [i]);
5432                                 patch_info->type = MONO_PATCH_INFO_NONE;
5433                         }
5434                         else {
5435                                 guint32 size;
5436
5437                                 /* Compute size of code following the push <OFFSET> */
5438 #if defined(__default_codegen__)
5439                                 size = 5 + 5;
5440 #elif defined(__native_client_codegen__)
5441                                 code = mono_nacl_align (code);
5442                                 size = kNaClAlignment;
5443 #endif
5444                                 /*This is aligned to 16 bytes by the callee. This way we save a few bytes here.*/
5445
5446                                 if ((code - cfg->native_code) - throw_ip < 126 - size) {
5447                                         /* Use the shorter form */
5448                                         buf = buf2 = code;
5449                                         x86_push_imm (code, 0);
5450                                 }
5451                                 else {
5452                                         buf = code;
5453                                         x86_push_imm (code, 0xf0f0f0f0);
5454                                         buf2 = code;
5455                                 }
5456
5457                                 if (nthrows < 16) {
5458                                         exc_classes [nthrows] = exc_class;
5459                                         exc_throw_start [nthrows] = code;
5460                                 }
5461
5462                                 x86_push_imm (code, exc_class->type_token - MONO_TOKEN_TYPE_DEF);
5463                                 patch_info->data.name = "mono_arch_throw_corlib_exception";
5464                                 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
5465                                 patch_info->ip.i = code - cfg->native_code;
5466                                 x86_call_code (code, 0);
5467                                 x86_push_imm (buf, (code - cfg->native_code) - throw_ip);
5468                                 while (buf < buf2)
5469                                         x86_nop (buf);
5470
5471                                 if (nthrows < 16) {
5472                                         exc_throw_end [nthrows] = code;
5473                                         nthrows ++;
5474                                 }
5475                         }
5476                         break;
5477                 }
5478                 default:
5479                         /* do nothing */
5480                         break;
5481                 }
5482         }
5483
5484         cfg->code_len = code - cfg->native_code;
5485
5486         g_assert (cfg->code_len < cfg->code_size);
5487 }
5488
5489 void
5490 mono_arch_flush_icache (guint8 *code, gint size)
5491 {
5492         /* not needed */
5493 }
5494
5495 void
5496 mono_arch_flush_register_windows (void)
5497 {
5498 }
5499
5500 gboolean 
5501 mono_arch_is_inst_imm (gint64 imm)
5502 {
5503         return TRUE;
5504 }
5505
5506 /*
5507  * Support for fast access to the thread-local lmf structure using the GS
5508  * segment register on NPTL + kernel 2.6.x.
5509  */
5510
5511 static gboolean tls_offset_inited = FALSE;
5512
5513 void
5514 mono_arch_setup_jit_tls_data (MonoJitTlsData *tls)
5515 {
5516         if (!tls_offset_inited) {
5517                 if (!getenv ("MONO_NO_TLS")) {
5518 #ifdef TARGET_WIN32
5519                         /* 
5520                          * We need to init this multiple times, since when we are first called, the key might not
5521                          * be initialized yet.
5522                          */
5523                         appdomain_tls_offset = mono_domain_get_tls_key ();
5524                         lmf_tls_offset = mono_get_jit_tls_key ();
5525
5526                         /* Only 64 tls entries can be accessed using inline code */
5527                         if (appdomain_tls_offset >= 64)
5528                                 appdomain_tls_offset = -1;
5529                         if (lmf_tls_offset >= 64)
5530                                 lmf_tls_offset = -1;
5531 #else
5532 #if MONO_XEN_OPT
5533                         optimize_for_xen = access ("/proc/xen", F_OK) == 0;
5534 #endif
5535                         tls_offset_inited = TRUE;
5536                         appdomain_tls_offset = mono_domain_get_tls_offset ();
5537                         lmf_tls_offset = mono_get_lmf_tls_offset ();
5538                         lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset ();
5539 #endif
5540                 }
5541         }               
5542 }
5543
5544 void
5545 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
5546 {
5547 }
5548
5549 #ifdef MONO_ARCH_HAVE_IMT
5550
5551 // Linear handler, the bsearch head compare is shorter
5552 //[2 + 4] x86_alu_reg_imm (code, X86_CMP, ins->sreg1, ins->inst_imm);
5553 //[1 + 1] x86_branch8(inst,cond,imm,is_signed)
5554 //        x86_patch(ins,target)
5555 //[1 + 5] x86_jump_mem(inst,mem)
5556
5557 #define CMP_SIZE 6
5558 #if defined(__default_codegen__)
5559 #define BR_SMALL_SIZE 2
5560 #define BR_LARGE_SIZE 5
5561 #elif defined(__native_client_codegen__)
5562 /* I suspect the size calculation below is actually incorrect. */
5563 /* TODO: fix the calculation that uses these sizes.  */
5564 #define BR_SMALL_SIZE 16
5565 #define BR_LARGE_SIZE 12
5566 #endif  /*__native_client_codegen__*/
5567 #define JUMP_IMM_SIZE 6
5568 #define ENABLE_WRONG_METHOD_CHECK 0
5569 #define DEBUG_IMT 0
5570
5571 static int
5572 imt_branch_distance (MonoIMTCheckItem **imt_entries, int start, int target)
5573 {
5574         int i, distance = 0;
5575         for (i = start; i < target; ++i)
5576                 distance += imt_entries [i]->chunk_size;
5577         return distance;
5578 }
5579
5580 /*
5581  * LOCKING: called with the domain lock held
5582  */
5583 gpointer
5584 mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
5585         gpointer fail_tramp)
5586 {
5587         int i;
5588         int size = 0;
5589         guint8 *code, *start;
5590
5591         for (i = 0; i < count; ++i) {
5592                 MonoIMTCheckItem *item = imt_entries [i];
5593                 if (item->is_equals) {
5594                         if (item->check_target_idx) {
5595                                 if (!item->compare_done)
5596                                         item->chunk_size += CMP_SIZE;
5597                                 item->chunk_size += BR_SMALL_SIZE + JUMP_IMM_SIZE;
5598                         } else {
5599                                 if (fail_tramp) {
5600                                         item->chunk_size += CMP_SIZE + BR_SMALL_SIZE + JUMP_IMM_SIZE * 2;
5601                                 } else {
5602                                         item->chunk_size += JUMP_IMM_SIZE;
5603 #if ENABLE_WRONG_METHOD_CHECK
5604                                         item->chunk_size += CMP_SIZE + BR_SMALL_SIZE + 1;
5605 #endif
5606                                 }
5607                         }
5608                 } else {
5609                         item->chunk_size += CMP_SIZE + BR_LARGE_SIZE;
5610                         imt_entries [item->check_target_idx]->compare_done = TRUE;
5611                 }
5612                 size += item->chunk_size;
5613         }
5614 #if defined(__native_client__) && defined(__native_client_codegen__)
5615         /* In Native Client, we don't re-use thunks, allocate from the */
5616         /* normal code manager paths. */
5617         code = mono_domain_code_reserve (domain, size);
5618 #else
5619         if (fail_tramp)
5620                 code = mono_method_alloc_generic_virtual_thunk (domain, size);
5621         else
5622                 code = mono_domain_code_reserve (domain, size);
5623 #endif
5624         start = code;
5625         for (i = 0; i < count; ++i) {
5626                 MonoIMTCheckItem *item = imt_entries [i];
5627                 item->code_target = code;
5628                 if (item->is_equals) {
5629                         if (item->check_target_idx) {
5630                                 if (!item->compare_done)
5631                                         x86_alu_reg_imm (code, X86_CMP, MONO_ARCH_IMT_REG, (guint32)item->key);
5632                                 item->jmp_code = code;
5633                                 x86_branch8 (code, X86_CC_NE, 0, FALSE);
5634                                 if (item->has_target_code)
5635                                         x86_jump_code (code, item->value.target_code);
5636                                 else
5637                                         x86_jump_mem (code, & (vtable->vtable [item->value.vtable_slot]));
5638                         } else {
5639                                 if (fail_tramp) {
5640                                         x86_alu_reg_imm (code, X86_CMP, MONO_ARCH_IMT_REG, (guint32)item->key);
5641                                         item->jmp_code = code;
5642                                         x86_branch8 (code, X86_CC_NE, 0, FALSE);
5643                                         if (item->has_target_code)
5644                                                 x86_jump_code (code, item->value.target_code);
5645                                         else
5646                                                 x86_jump_mem (code, & (vtable->vtable [item->value.vtable_slot]));
5647                                         x86_patch (item->jmp_code, code);
5648                                         x86_jump_code (code, fail_tramp);
5649                                         item->jmp_code = NULL;
5650                                 } else {
5651                                         /* enable the commented code to assert on wrong method */
5652 #if ENABLE_WRONG_METHOD_CHECK
5653                                         x86_alu_reg_imm (code, X86_CMP, MONO_ARCH_IMT_REG, (guint32)item->key);
5654                                         item->jmp_code = code;
5655                                         x86_branch8 (code, X86_CC_NE, 0, FALSE);
5656 #endif
5657                                         if (item->has_target_code)
5658                                                 x86_jump_code (code, item->value.target_code);
5659                                         else
5660                                                 x86_jump_mem (code, & (vtable->vtable [item->value.vtable_slot]));
5661 #if ENABLE_WRONG_METHOD_CHECK
5662                                         x86_patch (item->jmp_code, code);
5663                                         x86_breakpoint (code);
5664                                         item->jmp_code = NULL;
5665 #endif
5666                                 }
5667                         }
5668                 } else {
5669                         x86_alu_reg_imm (code, X86_CMP, MONO_ARCH_IMT_REG, (guint32)item->key);
5670                         item->jmp_code = code;
5671                         if (x86_is_imm8 (imt_branch_distance (imt_entries, i, item->check_target_idx)))
5672                                 x86_branch8 (code, X86_CC_GE, 0, FALSE);
5673                         else
5674                                 x86_branch32 (code, X86_CC_GE, 0, FALSE);
5675                 }
5676         }
5677         /* patch the branches to get to the target items */
5678         for (i = 0; i < count; ++i) {
5679                 MonoIMTCheckItem *item = imt_entries [i];
5680                 if (item->jmp_code) {
5681                         if (item->check_target_idx) {
5682                                 x86_patch (item->jmp_code, imt_entries [item->check_target_idx]->code_target);
5683                         }
5684                 }
5685         }
5686
5687         if (!fail_tramp)
5688                 mono_stats.imt_thunks_size += code - start;
5689         g_assert (code - start <= size);
5690
5691 #if DEBUG_IMT
5692         {
5693                 char *buff = g_strdup_printf ("thunk_for_class_%s_%s_entries_%d", vtable->klass->name_space, vtable->klass->name, count);
5694                 mono_disassemble_code (NULL, (guint8*)start, code - start, buff);
5695                 g_free (buff);
5696         }
5697 #endif
5698         if (mono_jit_map_is_enabled ()) {
5699                 char *buff;
5700                 if (vtable)
5701                         buff = g_strdup_printf ("imt_%s_%s_entries_%d", vtable->klass->name_space, vtable->klass->name, count);
5702                 else
5703                         buff = g_strdup_printf ("imt_thunk_entries_%d", count);
5704                 mono_emit_jit_tramp (start, code - start, buff);
5705                 g_free (buff);
5706         }
5707
5708         nacl_domain_code_validate (domain, &start, size, &code);
5709
5710         return start;
5711 }
5712
5713 MonoMethod*
5714 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
5715 {
5716         return (MonoMethod*) regs [MONO_ARCH_IMT_REG];
5717 }
5718 #endif
5719
5720 MonoVTable*
5721 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
5722 {
5723         return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG];
5724 }
5725
5726 GSList*
5727 mono_arch_get_cie_program (void)
5728 {
5729         GSList *l = NULL;
5730
5731         mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, X86_ESP, 4);
5732         mono_add_unwind_op_offset (l, (guint8*)NULL, (guint8*)NULL, X86_NREG, -4);
5733
5734         return l;
5735 }
5736
5737 MonoInst*
5738 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
5739 {
5740         MonoInst *ins = NULL;
5741         int opcode = 0;
5742
5743         if (cmethod->klass == mono_defaults.math_class) {
5744                 if (strcmp (cmethod->name, "Sin") == 0) {
5745                         opcode = OP_SIN;
5746                 } else if (strcmp (cmethod->name, "Cos") == 0) {
5747                         opcode = OP_COS;
5748                 } else if (strcmp (cmethod->name, "Tan") == 0) {
5749                         opcode = OP_TAN;
5750                 } else if (strcmp (cmethod->name, "Atan") == 0) {
5751                         opcode = OP_ATAN;
5752                 } else if (strcmp (cmethod->name, "Sqrt") == 0) {
5753                         opcode = OP_SQRT;
5754                 } else if (strcmp (cmethod->name, "Abs") == 0 && fsig->params [0]->type == MONO_TYPE_R8) {
5755                         opcode = OP_ABS;
5756                 } else if (strcmp (cmethod->name, "Round") == 0 && fsig->param_count == 1 && fsig->params [0]->type == MONO_TYPE_R8) {
5757                         opcode = OP_ROUND;
5758                 }
5759                 
5760                 if (opcode) {
5761                         MONO_INST_NEW (cfg, ins, opcode);
5762                         ins->type = STACK_R8;
5763                         ins->dreg = mono_alloc_freg (cfg);
5764                         ins->sreg1 = args [0]->dreg;
5765                         MONO_ADD_INS (cfg->cbb, ins);
5766                 }
5767
5768                 if (cfg->opt & MONO_OPT_CMOV) {
5769                         int opcode = 0;
5770
5771                         if (strcmp (cmethod->name, "Min") == 0) {
5772                                 if (fsig->params [0]->type == MONO_TYPE_I4)
5773                                         opcode = OP_IMIN;
5774                         } else if (strcmp (cmethod->name, "Max") == 0) {
5775                                 if (fsig->params [0]->type == MONO_TYPE_I4)
5776                                         opcode = OP_IMAX;
5777                         }               
5778
5779                         if (opcode) {
5780                                 MONO_INST_NEW (cfg, ins, opcode);
5781                                 ins->type = STACK_I4;
5782                                 ins->dreg = mono_alloc_ireg (cfg);
5783                                 ins->sreg1 = args [0]->dreg;
5784                                 ins->sreg2 = args [1]->dreg;
5785                                 MONO_ADD_INS (cfg->cbb, ins);
5786                         }
5787                 }
5788
5789 #if 0
5790                 /* OP_FREM is not IEEE compatible */
5791                 else if (strcmp (cmethod->name, "IEEERemainder") == 0) {
5792                         MONO_INST_NEW (cfg, ins, OP_FREM);
5793                         ins->inst_i0 = args [0];
5794                         ins->inst_i1 = args [1];
5795                 }
5796 #endif
5797         }
5798
5799         return ins;
5800 }
5801
5802 gboolean
5803 mono_arch_print_tree (MonoInst *tree, int arity)
5804 {
5805         return 0;
5806 }
5807
5808 MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
5809 {
5810         MonoInst* ins;
5811
5812         return NULL;
5813
5814         if (appdomain_tls_offset == -1)
5815                 return NULL;
5816
5817         MONO_INST_NEW (cfg, ins, OP_TLS_GET);
5818         ins->inst_offset = appdomain_tls_offset;
5819         return ins;
5820 }
5821
5822 guint32
5823 mono_arch_get_patch_offset (guint8 *code)
5824 {
5825         if ((code [0] == 0x8b) && (x86_modrm_mod (code [1]) == 0x2))
5826                 return 2;
5827         else if ((code [0] == 0xba))
5828                 return 1;
5829         else if ((code [0] == 0x68))
5830                 /* push IMM */
5831                 return 1;
5832         else if ((code [0] == 0xff) && (x86_modrm_reg (code [1]) == 0x6))
5833                 /* push <OFFSET>(<REG>) */
5834                 return 2;
5835         else if ((code [0] == 0xff) && (x86_modrm_reg (code [1]) == 0x2))
5836                 /* call *<OFFSET>(<REG>) */
5837                 return 2;
5838         else if ((code [0] == 0xdd) || (code [0] == 0xd9))
5839                 /* fldl <ADDR> */
5840                 return 2;
5841         else if ((code [0] == 0x58) && (code [1] == 0x05))
5842                 /* pop %eax; add <OFFSET>, %eax */
5843                 return 2;
5844         else if ((code [0] >= 0x58) && (code [0] <= 0x58 + X86_NREG) && (code [1] == 0x81))
5845                 /* pop <REG>; add <OFFSET>, <REG> */
5846                 return 3;
5847         else if ((code [0] >= 0xb8) && (code [0] < 0xb8 + 8))
5848                 /* mov <REG>, imm */
5849                 return 1;
5850         else {
5851                 g_assert_not_reached ();
5852                 return -1;
5853         }
5854 }
5855
5856 /**
5857  * mono_breakpoint_clean_code:
5858  *
5859  * Copy @size bytes from @code - @offset to the buffer @buf. If the debugger inserted software
5860  * breakpoints in the original code, they are removed in the copy.
5861  *
5862  * Returns TRUE if no sw breakpoint was present.
5863  */
5864 gboolean
5865 mono_breakpoint_clean_code (guint8 *method_start, guint8 *code, int offset, guint8 *buf, int size)
5866 {
5867         int i;
5868         gboolean can_write = TRUE;
5869         /*
5870          * If method_start is non-NULL we need to perform bound checks, since we access memory
5871          * at code - offset we could go before the start of the method and end up in a different
5872          * page of memory that is not mapped or read incorrect data anyway. We zero-fill the bytes
5873          * instead.
5874          */
5875         if (!method_start || code - offset >= method_start) {
5876                 memcpy (buf, code - offset, size);
5877         } else {
5878                 int diff = code - method_start;
5879                 memset (buf, 0, size);
5880                 memcpy (buf + offset - diff, method_start, diff + size - offset);
5881         }
5882         code -= offset;
5883         for (i = 0; i < MONO_BREAKPOINT_ARRAY_SIZE; ++i) {
5884                 int idx = mono_breakpoint_info_index [i];
5885                 guint8 *ptr;
5886                 if (idx < 1)
5887                         continue;
5888                 ptr = mono_breakpoint_info [idx].address;
5889                 if (ptr >= code && ptr < code + size) {
5890                         guint8 saved_byte = mono_breakpoint_info [idx].saved_byte;
5891                         can_write = FALSE;
5892                         /*g_print ("patching %p with 0x%02x (was: 0x%02x)\n", ptr, saved_byte, buf [ptr - code]);*/
5893                         buf [ptr - code] = saved_byte;
5894                 }
5895         }
5896         return can_write;
5897 }
5898
5899 /*
5900  * mono_x86_get_this_arg_offset:
5901  *
5902  *   Return the offset of the stack location where this is passed during a virtual
5903  * call.
5904  */
5905 guint32
5906 mono_x86_get_this_arg_offset (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig)
5907 {
5908         return 0;
5909 }
5910
5911 gpointer
5912 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
5913 {
5914         guint32 esp = regs [X86_ESP];
5915         CallInfo *cinfo = NULL;
5916         gpointer res;
5917         int offset;
5918
5919         offset = 0;
5920
5921         /*
5922          * The stack looks like:
5923          * <other args>
5924          * <this=delegate>
5925          * <return addr>
5926          * <4 pointers pushed by mono_arch_create_trampoline_code ()>
5927          */
5928         res = (((MonoObject**)esp) [5 + (offset / 4)]);
5929         if (cinfo)
5930                 g_free (cinfo);
5931         return res;
5932 }
5933
5934 #define MAX_ARCH_DELEGATE_PARAMS 10
5935
5936 static gpointer
5937 get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *code_len)
5938 {
5939         guint8 *code, *start;
5940         int code_reserve = 64;
5941
5942         /*
5943          * The stack contains:
5944          * <delegate>
5945          * <return addr>
5946          */
5947
5948         if (has_target) {
5949                 start = code = mono_global_codeman_reserve (code_reserve);
5950
5951                 /* Replace the this argument with the target */
5952                 x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4);
5953                 x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoDelegate, target), 4);
5954                 x86_mov_membase_reg (code, X86_ESP, 4, X86_ECX, 4);
5955                 x86_jump_membase (code, X86_EAX, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
5956
5957                 g_assert ((code - start) < code_reserve);
5958         } else {
5959                 int i = 0;
5960                 /* 8 for mov_reg and jump, plus 8 for each parameter */
5961 #ifdef __native_client_codegen__
5962                 /* TODO: calculate this size correctly */
5963                 code_reserve = 13 + (param_count * 8) + 2 * kNaClAlignment;
5964 #else
5965                 code_reserve = 8 + (param_count * 8);
5966 #endif  /* __native_client_codegen__ */
5967                 /*
5968                  * The stack contains:
5969                  * <args in reverse order>
5970                  * <delegate>
5971                  * <return addr>
5972                  *
5973                  * and we need:
5974                  * <args in reverse order>
5975                  * <return addr>
5976                  * 
5977                  * without unbalancing the stack.
5978                  * So move each arg up a spot in the stack (overwriting un-needed 'this' arg)
5979                  * and leaving original spot of first arg as placeholder in stack so
5980                  * when callee pops stack everything works.
5981                  */
5982
5983                 start = code = mono_global_codeman_reserve (code_reserve);
5984
5985                 /* store delegate for access to method_ptr */
5986                 x86_mov_reg_membase (code, X86_ECX, X86_ESP, 4, 4);
5987
5988                 /* move args up */
5989                 for (i = 0; i < param_count; ++i) {
5990                         x86_mov_reg_membase (code, X86_EAX, X86_ESP, (i+2)*4, 4);
5991                         x86_mov_membase_reg (code, X86_ESP, (i+1)*4, X86_EAX, 4);
5992                 }
5993
5994                 x86_jump_membase (code, X86_ECX, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
5995
5996                 g_assert ((code - start) < code_reserve);
5997         }
5998
5999         nacl_global_codeman_validate(&start, code_reserve, &code);
6000         mono_debug_add_delegate_trampoline (start, code - start);
6001
6002         if (code_len)
6003                 *code_len = code - start;
6004
6005         if (mono_jit_map_is_enabled ()) {
6006                 char *buff;
6007                 if (has_target)
6008                         buff = (char*)"delegate_invoke_has_target";
6009                 else
6010                         buff = g_strdup_printf ("delegate_invoke_no_target_%d", param_count);
6011                 mono_emit_jit_tramp (start, code - start, buff);
6012                 if (!has_target)
6013                         g_free (buff);
6014         }
6015
6016         return start;
6017 }
6018
6019 GSList*
6020 mono_arch_get_delegate_invoke_impls (void)
6021 {
6022         GSList *res = NULL;
6023         guint8 *code;
6024         guint32 code_len;
6025         int i;
6026
6027         code = get_delegate_invoke_impl (TRUE, 0, &code_len);
6028         res = g_slist_prepend (res, mono_tramp_info_create (g_strdup ("delegate_invoke_impl_has_target"), code, code_len, NULL, NULL));
6029
6030         for (i = 0; i < MAX_ARCH_DELEGATE_PARAMS; ++i) {
6031                 code = get_delegate_invoke_impl (FALSE, i, &code_len);
6032                 res = g_slist_prepend (res, mono_tramp_info_create (g_strdup_printf ("delegate_invoke_impl_target_%d", i), code, code_len, NULL, NULL));
6033         }
6034
6035         return res;
6036 }
6037
6038 gpointer
6039 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6040 {
6041         guint8 *code, *start;
6042
6043         if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6044                 return NULL;
6045
6046         /* FIXME: Support more cases */
6047         if (MONO_TYPE_ISSTRUCT (sig->ret))
6048                 return NULL;
6049
6050         /*
6051          * The stack contains:
6052          * <delegate>
6053          * <return addr>
6054          */
6055
6056         if (has_target) {
6057                 static guint8* cached = NULL;
6058                 if (cached)
6059                         return cached;
6060
6061                 if (mono_aot_only)
6062                         start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6063                 else
6064                         start = get_delegate_invoke_impl (TRUE, 0, NULL);
6065
6066                 mono_memory_barrier ();
6067
6068                 cached = start;
6069         } else {
6070                 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6071                 int i = 0;
6072
6073                 for (i = 0; i < sig->param_count; ++i)
6074                         if (!mono_is_regsize_var (sig->params [i]))
6075                                 return NULL;
6076
6077                 code = cache [sig->param_count];
6078                 if (code)
6079                         return code;
6080
6081                 if (mono_aot_only) {
6082                         char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6083                         start = mono_aot_get_trampoline (name);
6084                         g_free (name);
6085                 } else {
6086                         start = get_delegate_invoke_impl (FALSE, sig->param_count, NULL);
6087                 }
6088
6089                 mono_memory_barrier ();
6090
6091                 cache [sig->param_count] = start;
6092         }
6093
6094         return start;
6095 }
6096
6097 gpointer
6098 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6099 {
6100         switch (reg) {
6101         case X86_EAX: return (gpointer)ctx->eax;
6102         case X86_EBX: return (gpointer)ctx->ebx;
6103         case X86_ECX: return (gpointer)ctx->ecx;
6104         case X86_EDX: return (gpointer)ctx->edx;
6105         case X86_ESP: return (gpointer)ctx->esp;
6106         case X86_EBP: return (gpointer)ctx->ebp;
6107         case X86_ESI: return (gpointer)ctx->esi;
6108         case X86_EDI: return (gpointer)ctx->edi;
6109         default: g_assert_not_reached ();
6110         }
6111 }
6112
6113 #ifdef MONO_ARCH_SIMD_INTRINSICS
6114
6115 static MonoInst*
6116 get_float_to_x_spill_area (MonoCompile *cfg)
6117 {
6118         if (!cfg->fconv_to_r8_x_var) {
6119                 cfg->fconv_to_r8_x_var = mono_compile_create_var (cfg, &mono_defaults.double_class->byval_arg, OP_LOCAL);
6120                 cfg->fconv_to_r8_x_var->flags |= MONO_INST_VOLATILE; /*FIXME, use the don't regalloc flag*/
6121         }       
6122         return cfg->fconv_to_r8_x_var;
6123 }
6124
6125 /*
6126  * Convert all fconv opts that MONO_OPT_SSE2 would get wrong. 
6127  */
6128 void
6129 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6130 {
6131         MonoInst *fconv;
6132         int dreg, src_opcode;
6133
6134         if (!(cfg->opt & MONO_OPT_SSE2) || !(cfg->opt & MONO_OPT_SIMD) || COMPILE_LLVM (cfg))
6135                 return;
6136
6137         switch (src_opcode = ins->opcode) {
6138         case OP_FCONV_TO_I1:
6139         case OP_FCONV_TO_U1:
6140         case OP_FCONV_TO_I2:
6141         case OP_FCONV_TO_U2:
6142         case OP_FCONV_TO_I4:
6143         case OP_FCONV_TO_I:
6144                 break;
6145         default:
6146                 return;
6147         }
6148
6149         /* dreg is the IREG and sreg1 is the FREG */
6150         MONO_INST_NEW (cfg, fconv, OP_FCONV_TO_R8_X);
6151         fconv->klass = NULL; /*FIXME, what can I use here as the Mono.Simd lib might not be loaded yet*/
6152         fconv->sreg1 = ins->sreg1;
6153         fconv->dreg = mono_alloc_ireg (cfg);
6154         fconv->type = STACK_VTYPE;
6155         fconv->backend.spill_var = get_float_to_x_spill_area (cfg);
6156
6157         mono_bblock_insert_before_ins (cfg->cbb, ins, fconv);
6158
6159         dreg = ins->dreg;
6160         NULLIFY_INS (ins);
6161         ins->opcode = OP_XCONV_R8_TO_I4;
6162
6163         ins->klass = mono_defaults.int32_class;
6164         ins->sreg1 = fconv->dreg;
6165         ins->dreg = dreg;
6166         ins->type = STACK_I4;
6167         ins->backend.source_opcode = src_opcode;
6168 }
6169
6170 #endif /* #ifdef MONO_ARCH_SIMD_INTRINSICS */
6171
6172 void
6173 mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *long_ins)
6174 {
6175         MonoInst *ins;
6176         int vreg;
6177
6178         if (long_ins->opcode == OP_LNEG) {
6179                 ins = long_ins;
6180                 MONO_EMIT_NEW_UNALU (cfg, OP_INEG, ins->dreg + 1, ins->sreg1 + 1);
6181                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, ins->dreg + 2, ins->sreg1 + 2, 0);
6182                 MONO_EMIT_NEW_UNALU (cfg, OP_INEG, ins->dreg + 2, ins->dreg + 2);
6183                 NULLIFY_INS (ins);
6184                 return;
6185         }
6186
6187 #ifdef MONO_ARCH_SIMD_INTRINSICS
6188
6189         if (!(cfg->opt & MONO_OPT_SIMD))
6190                 return;
6191         
6192         /*TODO move this to simd-intrinsic.c once we support sse 4.1 dword extractors since we need the runtime caps info */ 
6193         switch (long_ins->opcode) {
6194         case OP_EXTRACT_I8:
6195                 vreg = long_ins->sreg1;
6196         
6197                 if (long_ins->inst_c0) {
6198                         MONO_INST_NEW (cfg, ins, OP_PSHUFLED);
6199                         ins->klass = long_ins->klass;
6200                         ins->sreg1 = long_ins->sreg1;
6201                         ins->inst_c0 = 2;
6202                         ins->type = STACK_VTYPE;
6203                         ins->dreg = vreg = alloc_ireg (cfg);
6204                         MONO_ADD_INS (cfg->cbb, ins);
6205                 }
6206         
6207                 MONO_INST_NEW (cfg, ins, OP_EXTRACT_I4);
6208                 ins->klass = mono_defaults.int32_class;
6209                 ins->sreg1 = vreg;
6210                 ins->type = STACK_I4;
6211                 ins->dreg = long_ins->dreg + 1;
6212                 MONO_ADD_INS (cfg->cbb, ins);
6213         
6214                 MONO_INST_NEW (cfg, ins, OP_PSHUFLED);
6215                 ins->klass = long_ins->klass;
6216                 ins->sreg1 = long_ins->sreg1;
6217                 ins->inst_c0 = long_ins->inst_c0 ? 3 : 1;
6218                 ins->type = STACK_VTYPE;
6219                 ins->dreg = vreg = alloc_ireg (cfg);
6220                 MONO_ADD_INS (cfg->cbb, ins);
6221         
6222                 MONO_INST_NEW (cfg, ins, OP_EXTRACT_I4);
6223                 ins->klass = mono_defaults.int32_class;
6224                 ins->sreg1 = vreg;
6225                 ins->type = STACK_I4;
6226                 ins->dreg = long_ins->dreg + 2;
6227                 MONO_ADD_INS (cfg->cbb, ins);
6228         
6229                 long_ins->opcode = OP_NOP;
6230                 break;
6231         case OP_INSERTX_I8_SLOW:
6232                 MONO_INST_NEW (cfg, ins, OP_INSERTX_I4_SLOW);
6233                 ins->dreg = long_ins->dreg;
6234                 ins->sreg1 = long_ins->dreg;
6235                 ins->sreg2 = long_ins->sreg2 + 1;
6236                 ins->inst_c0 = long_ins->inst_c0 * 2;
6237                 MONO_ADD_INS (cfg->cbb, ins);
6238
6239                 MONO_INST_NEW (cfg, ins, OP_INSERTX_I4_SLOW);
6240                 ins->dreg = long_ins->dreg;
6241                 ins->sreg1 = long_ins->dreg;
6242                 ins->sreg2 = long_ins->sreg2 + 2;
6243                 ins->inst_c0 = long_ins->inst_c0 * 2 + 1;
6244                 MONO_ADD_INS (cfg->cbb, ins);
6245
6246                 long_ins->opcode = OP_NOP;
6247                 break;
6248         case OP_EXPAND_I8:
6249                 MONO_INST_NEW (cfg, ins, OP_ICONV_TO_X);
6250                 ins->dreg = long_ins->dreg;
6251                 ins->sreg1 = long_ins->sreg1 + 1;
6252                 ins->klass = long_ins->klass;
6253                 ins->type = STACK_VTYPE;
6254                 MONO_ADD_INS (cfg->cbb, ins);
6255
6256                 MONO_INST_NEW (cfg, ins, OP_INSERTX_I4_SLOW);
6257                 ins->dreg = long_ins->dreg;
6258                 ins->sreg1 = long_ins->dreg;
6259                 ins->sreg2 = long_ins->sreg1 + 2;
6260                 ins->inst_c0 = 1;
6261                 ins->klass = long_ins->klass;
6262                 ins->type = STACK_VTYPE;
6263                 MONO_ADD_INS (cfg->cbb, ins);
6264
6265                 MONO_INST_NEW (cfg, ins, OP_PSHUFLED);
6266                 ins->dreg = long_ins->dreg;
6267                 ins->sreg1 = long_ins->dreg;;
6268                 ins->inst_c0 = 0x44; /*Magic number for swizzling (X,Y,X,Y)*/
6269                 ins->klass = long_ins->klass;
6270                 ins->type = STACK_VTYPE;
6271                 MONO_ADD_INS (cfg->cbb, ins);
6272
6273                 long_ins->opcode = OP_NOP;
6274                 break;
6275         }
6276 #endif /* MONO_ARCH_SIMD_INTRINSICS */
6277 }
6278
6279 /*MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD*/
6280 gpointer
6281 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause, MonoContext *ctx, gpointer new_value)
6282 {
6283         int offset;
6284         gpointer *sp, old_value;
6285         char *bp;
6286         const unsigned char *handler;
6287
6288         /*Decode the first instruction to figure out where did we store the spvar*/
6289         /*Our jit MUST generate the following:
6290          mov %esp, -?(%ebp)
6291          Which is encoded as: 0x89 mod_rm.
6292          mod_rm (esp, ebp, imm) which can be: (imm will never be zero)
6293                 mod (reg + imm8):  01 reg(esp): 100 rm(ebp): 101 -> 01100101 (0x65)
6294                 mod (reg + imm32): 10 reg(esp): 100 rm(ebp): 101 -> 10100101 (0xA5)
6295         */
6296         handler = clause->handler_start;
6297
6298         if (*handler != 0x89)
6299                 return NULL;
6300
6301         ++handler;
6302
6303         if (*handler == 0x65)
6304                 offset = *(signed char*)(handler + 1);
6305         else if (*handler == 0xA5)
6306                 offset = *(int*)(handler + 1);
6307         else
6308                 return NULL;
6309
6310         /*Load the spvar*/
6311         bp = MONO_CONTEXT_GET_BP (ctx);
6312         sp = *(gpointer*)(bp + offset);
6313
6314         old_value = *sp;
6315         if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6316                 return old_value;
6317
6318         *sp = new_value;
6319
6320         return old_value;
6321 }
6322
6323 /*
6324  * mono_aot_emit_load_got_addr:
6325  *
6326  *   Emit code to load the got address.
6327  * On x86, the result is placed into EBX.
6328  */
6329 guint8*
6330 mono_arch_emit_load_got_addr (guint8 *start, guint8 *code, MonoCompile *cfg, MonoJumpInfo **ji)
6331 {
6332         x86_call_imm (code, 0);
6333         /* 
6334          * The patch needs to point to the pop, since the GOT offset needs 
6335          * to be added to that address.
6336          */
6337         if (cfg)
6338                 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_GOT_OFFSET, NULL);
6339         else
6340                 *ji = mono_patch_info_list_prepend (*ji, code - start, MONO_PATCH_INFO_GOT_OFFSET, NULL);
6341         x86_pop_reg (code, MONO_ARCH_GOT_REG);
6342         x86_alu_reg_imm (code, X86_ADD, MONO_ARCH_GOT_REG, 0xf0f0f0f0);
6343
6344         return code;
6345 }
6346
6347 /*
6348  * mono_ppc_emit_load_aotconst:
6349  *
6350  *   Emit code to load the contents of the GOT slot identified by TRAMP_TYPE and
6351  * TARGET from the mscorlib GOT in full-aot code.
6352  * On x86, the GOT address is assumed to be in EBX, and the result is placed into 
6353  * EAX.
6354  */
6355 guint8*
6356 mono_arch_emit_load_aotconst (guint8 *start, guint8 *code, MonoJumpInfo **ji, int tramp_type, gconstpointer target)
6357 {
6358         /* Load the mscorlib got address */
6359         x86_mov_reg_membase (code, X86_EAX, MONO_ARCH_GOT_REG, sizeof (gpointer), 4);
6360         *ji = mono_patch_info_list_prepend (*ji, code - start, tramp_type, target);
6361         /* arch_emit_got_access () patches this */
6362         x86_mov_reg_membase (code, X86_EAX, X86_EAX, 0xf0f0f0f0, 4);
6363
6364         return code;
6365 }
6366
6367 /* Can't put this into mini-x86.h */
6368 gpointer
6369 mono_x86_get_signal_exception_trampoline (MonoTrampInfo **info, gboolean aot);
6370
6371 GSList *
6372 mono_arch_get_trampolines (gboolean aot)
6373 {
6374         MonoTrampInfo *info;
6375         GSList *tramps = NULL;
6376
6377         mono_x86_get_signal_exception_trampoline (&info, aot);
6378
6379         tramps = g_slist_append (tramps, info);
6380
6381         return tramps;
6382 }
6383
6384
6385 #if __APPLE__
6386 #define DBG_SIGNAL SIGBUS
6387 #else
6388 #define DBG_SIGNAL SIGSEGV
6389 #endif
6390
6391 /* Soft Debug support */
6392 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6393
6394 /*
6395  * mono_arch_set_breakpoint:
6396  *
6397  *   Set a breakpoint at the native code corresponding to JI at NATIVE_OFFSET.
6398  * The location should contain code emitted by OP_SEQ_POINT.
6399  */
6400 void
6401 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6402 {
6403         guint8 *code = ip;
6404
6405         /* 
6406          * In production, we will use int3 (has to fix the size in the md 
6407          * file). But that could confuse gdb, so during development, we emit a SIGSEGV
6408          * instead.
6409          */
6410         g_assert (code [0] == 0x90);
6411         x86_alu_reg_mem (code, X86_CMP, X86_EAX, (guint32)bp_trigger_page);
6412 }
6413
6414 /*
6415  * mono_arch_clear_breakpoint:
6416  *
6417  *   Clear the breakpoint at IP.
6418  */
6419 void
6420 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6421 {
6422         guint8 *code = ip;
6423         int i;
6424
6425         for (i = 0; i < 6; ++i)
6426                 x86_nop (code);
6427 }
6428         
6429 /*
6430  * mono_arch_start_single_stepping:
6431  *
6432  *   Start single stepping.
6433  */
6434 void
6435 mono_arch_start_single_stepping (void)
6436 {
6437         mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6438 }
6439         
6440 /*
6441  * mono_arch_stop_single_stepping:
6442  *
6443  *   Stop single stepping.
6444  */
6445 void
6446 mono_arch_stop_single_stepping (void)
6447 {
6448         mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6449 }
6450
6451 /*
6452  * mono_arch_is_single_step_event:
6453  *
6454  *   Return whenever the machine state in SIGCTX corresponds to a single
6455  * step event.
6456  */
6457 gboolean
6458 mono_arch_is_single_step_event (void *info, void *sigctx)
6459 {
6460 #ifdef TARGET_WIN32
6461         EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; /* Sometimes the address is off by 4 */
6462
6463         if ((einfo->ExceptionInformation[1] >= ss_trigger_page && (guint8*)einfo->ExceptionInformation[1] <= (guint8*)ss_trigger_page + 128))
6464                 return TRUE;
6465         else
6466                 return FALSE;
6467 #else
6468         siginfo_t* sinfo = (siginfo_t*) info;
6469         /* Sometimes the address is off by 4 */
6470         if (sinfo->si_signo == DBG_SIGNAL && (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128))
6471                 return TRUE;
6472         else
6473                 return FALSE;
6474 #endif
6475 }
6476
6477 gboolean
6478 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6479 {
6480 #ifdef TARGET_WIN32
6481         EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; /* Sometimes the address is off by 4 */
6482         if ((einfo->ExceptionInformation[1] >= bp_trigger_page && (guint8*)einfo->ExceptionInformation[1] <= (guint8*)bp_trigger_page + 128))
6483                 return TRUE;
6484         else
6485                 return FALSE;
6486 #else
6487         siginfo_t* sinfo = (siginfo_t*)info;
6488         /* Sometimes the address is off by 4 */
6489         if (sinfo->si_signo == DBG_SIGNAL && (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128))
6490                 return TRUE;
6491         else
6492                 return FALSE;
6493 #endif
6494 }
6495
6496 /*
6497  * mono_arch_get_ip_for_breakpoint:
6498  *
6499  *   See mini-amd64.c for docs.
6500  */
6501 guint8*
6502 mono_arch_get_ip_for_breakpoint (MonoJitInfo *ji, MonoContext *ctx)
6503 {
6504         guint8 *ip = MONO_CONTEXT_GET_IP (ctx);
6505
6506         return ip;
6507 }
6508
6509 #define BREAKPOINT_SIZE 6
6510
6511 /*
6512  * mono_arch_get_ip_for_single_step:
6513  *
6514  *   See mini-amd64.c for docs.
6515  */
6516 guint8*
6517 mono_arch_get_ip_for_single_step (MonoJitInfo *ji, MonoContext *ctx)
6518 {
6519         guint8 *ip = MONO_CONTEXT_GET_IP (ctx);
6520
6521         /* Size of x86_alu_reg_imm */
6522         ip += 6;
6523
6524         return ip;
6525 }
6526
6527 /*
6528  * mono_arch_skip_breakpoint:
6529  *
6530  *   See mini-amd64.c for docs.
6531  */
6532 void
6533 mono_arch_skip_breakpoint (MonoContext *ctx)
6534 {
6535         MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
6536 }
6537
6538 /*
6539  * mono_arch_skip_single_step:
6540  *
6541  *   See mini-amd64.c for docs.
6542  */
6543 void
6544 mono_arch_skip_single_step (MonoContext *ctx)
6545 {
6546         MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + 6);
6547 }
6548
6549 /*
6550  * mono_arch_get_seq_point_info:
6551  *
6552  *   See mini-amd64.c for docs.
6553  */
6554 gpointer
6555 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
6556 {
6557         NOT_IMPLEMENTED;
6558         return NULL;
6559 }
6560
6561 #endif
6562