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