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