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