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