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