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