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