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