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