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