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