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