(mono_analyze_stack): emit right CONV_UX opcodes: fixes bug 23547
[mono.git] / mono / jit / x86.brg
1 /*
2  * x86.brg: X86 code generator
3  *
4  * Author:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  */
9
10 #include <config.h>
11
12 #include <glib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #ifndef PLATFORM_WIN32
16 #include <signal.h>
17 #include <sys/syscall.h>
18 #endif
19
20 #include <mono/metadata/blob.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/loader.h>
23 #include <mono/metadata/object.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/appdomain.h>
26 #include <mono/arch/x86/x86-codegen.h>
27
28 #include "regset.h"
29 #include "jit.h"
30
31
32 void print_lmf (void);
33
34 #define MBTREE_TYPE  MBTree
35 #define MBCGEN_TYPE  MonoFlowGraph
36 #define MBCOST_DATA  MonoFlowGraph
37 #define MBALLOC_STATE mono_mempool_alloc (data->mp, sizeof (MBState))
38
39 typedef enum {
40         AMImmediate       = 0,  // ptr
41         AMBase            = 1,  // V[REG]  
42         AMIndex           = 2,  // V[REG*X] 
43         AMBaseIndex       = 3,  // V[REG*X][REG] 
44 } X86AddMode;
45
46 typedef struct {
47         int           offset;
48         X86AddMode    amode:2;
49         unsigned int  shift:2;
50         gint8         basereg;
51         gint8         indexreg;
52 } X86AddressInfo;
53
54 struct _MBTree {
55         guint16   op;
56         unsigned  last_instr:1;
57         
58         MBTree   *left, *right;
59         gpointer  state;
60         gpointer  emit;
61
62         gint32    addr;
63         gint32    cli_addr;
64
65         guint8    exclude_mask;
66
67         gint8     reg1;
68         gint8     reg2;
69         gint8     reg3;
70         
71         MonoValueType svt;
72
73         union {
74                 gint32 i;
75                 gint64 l;
76                 gpointer p;
77                 MonoBBlock *bb;
78                 MonoMethod *m;
79                 MonoClass *klass;
80                 MonoClassField *field;
81                 X86AddressInfo ainfo;
82                 MonoJitCallInfo ci;
83                 MonoJitFieldInfo fi;
84         } data;
85 };
86
87 gint64   mono_llmult        (gint64 a, gint64 b);
88 guint64  mono_llmult_ovf    (gpointer *exc, guint32 al, gint32 ah, guint32 bl, gint32 bh);
89 guint64  mono_llmult_ovf_un (gpointer *exc, guint32 al, guint32 ah, guint32 bl, guint32 bh);
90 gint64   mono_lldiv         (gint64 a, gint64 b);
91 gint64   mono_llrem         (gint64 a, gint64 b);
92 guint64  mono_lldiv_un      (guint64 a, guint64 b);
93 guint64  mono_llrem_un      (guint64 a, guint64 b);
94 gpointer mono_ldsflda       (MonoClass *klass, int offset);
95
96 gpointer arch_get_lmf_addr (void);
97
98 MonoArray*
99 mono_array_new_wrapper  (MonoClass *eclass, guint32 n);
100 MonoObject *
101 mono_object_new_wrapper (MonoClass *klass);
102 MonoString*
103 mono_ldstr_wrapper      (MonoImage *image, guint32 ind);
104
105 gpointer
106 get_mono_object_isinst (void);
107
108 #define MB_OPT_LEVEL 1
109
110 #if MB_OPT_LEVEL == 0
111 #define MB_USE_OPT1(c) 65535
112 #define MB_USE_OPT2(c) 65535
113 #endif
114 #if MB_OPT_LEVEL == 1
115 #define MB_USE_OPT1(c) c
116 #define MB_USE_OPT2(c) 65535
117 #endif
118 #if MB_OPT_LEVEL >= 2
119 #define MB_USE_OPT1(c) c
120 #define MB_USE_OPT2(c) c
121 #endif
122
123 //#define DEBUG
124
125 #define REAL_PRINT_REG(text,reg) \
126 mono_assert (reg >= 0); \
127 x86_push_reg (s->code, X86_EAX); \
128 x86_push_reg (s->code, X86_EDX); \
129 x86_push_reg (s->code, X86_ECX); \
130 x86_push_reg (s->code, reg); \
131 x86_push_imm (s->code, reg); \
132 x86_push_imm (s->code, text " %d %p\n"); \
133 x86_mov_reg_imm (s->code, X86_EAX, printf); \
134 x86_call_reg (s->code, X86_EAX); \
135 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 3*4); \
136 x86_pop_reg (s->code, X86_ECX); \
137 x86_pop_reg (s->code, X86_EDX); \
138 x86_pop_reg (s->code, X86_EAX); 
139
140 #ifdef DEBUG
141 #define MEMCOPY debug_memcpy
142 void *MEMCOPY (void *dest, const void *src, size_t n);
143
144 #define PRINT_REG(text,reg) REAL_PRINT_REG(text,reg)
145 #else
146
147 #define MEMCOPY memcpy
148
149 #define PRINT_REG(x,y)
150
151 #endif
152
153 /* The call instruction for virtual functions must have a known
154  * size (used by x86_magic_trampoline)
155  */
156 #define x86_call_virtual(inst,basereg,disp)                    \
157         do {                                                   \
158                 *(inst)++ = (unsigned char)0xff;               \
159                 x86_address_byte ((inst), 2, 2, (basereg));    \
160                 x86_imm_emit32 ((inst), (disp));               \
161         } while (0)
162
163 /* emit an exception if condition is fail */
164 #define EMIT_COND_SYSTEM_EXCEPTION(cond,signed,exc_name)       \
165         do {                                                   \
166                 gpointer t;                                    \
167                 x86_branch8 (s->code, cond, 10, signed);       \
168                 x86_push_imm (s->code, exc_name);              \
169                 t = arch_get_throw_exception_by_name ();       \
170                 mono_add_jump_info (s, s->code + 1,            \
171                                     MONO_JUMP_INFO_ABS, t);    \
172                 x86_call_code (s->code, 0);                    \
173         } while (0); 
174
175 %%
176
177 #
178 # terminal definitions
179 #
180
181 # constatnts
182 %term CONST_I4 CONST_I8 CONST_R4 CONST_R8
183 %term LDIND_I1 LDIND_U1 LDIND_I2 LDIND_U2 LDIND_I4 LDIND_REF LDIND_I8 LDIND_R4 LDIND_R8
184 %term LDIND_U4 LDIND_OBJ 
185 %term STIND_I1 STIND_I2 STIND_I4 STIND_REF STIND_I8 STIND_R4 STIND_R8 STIND_OBJ
186 %term ADDR_L ADDR_G ARG_I4 ARG_I8 ARG_R4 ARG_R8 ARG_OBJ ARG_STRING CALL_I4 CALL_I8 CALL_R8 CALL_VOID
187 %term BREAK SWITCH BR RET_VOID RET RET_OBJ ENDFINALLY
188 %term ADD ADD_OVF ADD_OVF_UN SUB SUB_OVF SUB_OVF_UN MUL MUL_OVF MUL_OVF_UN 
189 %term DIV DIV_UN REM REM_UN AND OR XOR SHL SHR SHR_UN NEG NOT
190 %term BLT BLT_UN BEQ BNE_UN BRTRUE BRFALSE BGE BGE_UN BLE BLE_UN BGT BGT_UN 
191 %term CEQ CLT CLT_UN CGT CGT_UN
192 %term CONV_I4 CONV_I1 CONV_I2 CONV_I8 CONV_U1 CONV_U2 CONV_U4 CONV_U8 CONV_R4 CONV_R8 CONV_R_UN
193 %term INTF_ADDR VFUNC_ADDR NOP NEWARR NEWARR_SPEC NEWOBJ NEWOBJ_SPEC NEWSTRUCT CPOBJ POP INITOBJ
194 %term ISINST CASTCLASS UNBOX
195 %term CONV_OVF_I1 CONV_OVF_U1 CONV_OVF_I2 CONV_OVF_U2 CONV_OVF_U4 CONV_OVF_U8 CONV_OVF_I4
196 %term CONV_OVF_I4_UN CONV_OVF_U1_UN CONV_OVF_U2_UN
197 %term CONV_OVF_I2_UN CONV_OVF_I8_UN CONV_OVF_I1_UN 
198 %term EXCEPTION THROW RETHROW HANDLER CHECKTHIS
199 %term LDLEN LDELEMA LDFTN LDVIRTFTN LDSTR LDSFLDA
200 %term REMOTE_LDFLDA REMOTE_STIND_I1 REMOTE_STIND_I2 REMOTE_STIND_I4 REMOTE_STIND_REF
201 %term REMOTE_STIND_I8 REMOTE_STIND_R4 REMOTE_STIND_R8 REMOTE_STIND_OBJ
202 #
203 # we start at stmt
204 #
205 %start stmt
206
207 #
208 # tree definitions
209 #
210
211 # integer constant folding
212 coni4: AND (coni4, coni4) {
213         tree->data.i = tree->left->data.i & tree->right->data.i;
214 }
215
216 coni4: OR (coni4, coni4) {
217         tree->data.i = tree->left->data.i | tree->right->data.i;
218 }
219
220 coni4: XOR (coni4, coni4) {
221         tree->data.i = tree->left->data.i ^ tree->right->data.i;
222 }
223
224 coni4: SHL (coni4, coni4) {
225         tree->data.i = tree->left->data.i << tree->right->data.i;
226 }
227
228 coni4: SHR (coni4, coni4) {
229         tree->data.i = tree->left->data.i >> tree->right->data.i;
230 }
231
232 coni4: NOT (coni4) {
233         tree->data.i = ~tree->left->data.i;
234 }
235
236 coni4: ADD (coni4, coni4) {
237         tree->data.i = tree->left->data.i + tree->right->data.i;
238 }
239
240 coni4: SUB (coni4, coni4) {
241         tree->data.i = tree->left->data.i - tree->right->data.i;
242 }
243
244 coni4: MUL (coni4, coni4) {
245         tree->data.i = tree->left->data.i * tree->right->data.i;
246 }
247
248 coni4: DIV (coni4, coni4) {
249         tree->data.i = tree->left->data.i / tree->right->data.i;
250 } cost {
251         MBCOND (tree->right->data.i)
252         return 0;
253 }
254
255 coni4: REM (coni4, coni4) {
256         tree->data.i = tree->left->data.i % tree->right->data.i;
257 } cost {
258         MBCOND (tree->right->data.i)
259         return 0;
260 }
261
262 coni4: CEQ (coni4, coni4) {
263         if (tree->left->data.i == tree->right->data.i)
264                 tree->data.i = 1;
265         else 
266                 tree->data.i = 0;
267 }
268
269 coni4: CGT (coni4, coni4) {
270         if (tree->left->data.i > tree->right->data.i)
271                 tree->data.i = 1;
272         else 
273                 tree->data.i = 0;
274 }
275
276 coni4: CLT (coni4, coni4) {
277         if (tree->left->data.i < tree->right->data.i)
278                 tree->data.i = 1;
279         else 
280                 tree->data.i = 0;
281 }
282
283 coni4: CONST_I4 {
284         /* do nothing */
285 }
286
287 #
288 # x86 adressing mode
289 #
290
291 acon: coni4 {
292         tree->data.ainfo.offset = tree->data.i;
293         tree->data.ainfo.amode = AMImmediate;
294 }
295
296 acon: ADDR_G {
297         tree->data.ainfo.offset = tree->data.i;
298         tree->data.ainfo.amode = AMImmediate;
299 }
300
301 acon: ADD (ADDR_G, coni4) {
302         tree->data.ainfo.offset = (unsigned)tree->left->data.p + tree->right->data.i;
303         tree->data.ainfo.amode = AMImmediate;
304 }
305
306 base: acon
307
308 base: reg {
309         tree->data.ainfo.offset = 0;
310         tree->data.ainfo.basereg = tree->reg1;
311         tree->data.ainfo.amode = AMBase;
312 }
313
314 base: ADD (reg, coni4) {
315         tree->data.ainfo.offset = tree->right->data.i;
316         tree->data.ainfo.basereg = tree->left->reg1;
317         tree->data.ainfo.amode = AMBase;
318 }
319
320 base: ADDR_L {
321         tree->data.ainfo.offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
322         tree->data.ainfo.basereg = X86_EBP;
323         tree->data.ainfo.amode = AMBase;
324 }
325
326 index: reg {
327         tree->data.ainfo.offset = 0;
328         tree->data.ainfo.indexreg = tree->reg1;
329         tree->data.ainfo.shift = 0;
330         tree->data.ainfo.amode = AMIndex;
331 }
332
333 index: SHL (reg, coni4) {
334         tree->data.ainfo.offset = 0;
335         tree->data.ainfo.amode = AMIndex;
336         tree->data.ainfo.indexreg = tree->left->reg1;
337         tree->data.ainfo.shift = tree->right->data.i;
338 } cost {
339         MBCOND (tree->right->data.i == 0 ||
340                 tree->right->data.i == 1 ||
341                 tree->right->data.i == 2 ||
342                 tree->right->data.i == 3);
343
344         return 0;
345 }
346
347 index: MUL (reg, coni4) {
348         static int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
349   
350         tree->data.ainfo.offset = 0;
351         tree->data.ainfo.amode = AMIndex;
352         tree->data.ainfo.indexreg = tree->left->reg1;
353         tree->data.ainfo.shift = fast_log2 [tree->right->data.i];
354 } cost {
355         MBCOND (tree->right->data.i == 1 ||
356                 tree->right->data.i == 2 ||
357                 tree->right->data.i == 4 ||
358                 tree->right->data.i == 8);
359
360         return 0;
361 }
362
363 addr: base
364
365 addr: index
366
367 addr: ADD (index, base) {
368         tree->data.ainfo.offset = tree->right->data.ainfo.offset;
369         tree->data.ainfo.basereg = tree->right->data.ainfo.basereg;
370         tree->data.ainfo.amode = tree->left->data.ainfo.amode | 
371                 tree->right->data.ainfo.amode;
372         tree->data.ainfo.shift = tree->left->data.ainfo.shift;
373         tree->data.ainfo.indexreg = tree->left->data.ainfo.indexreg;
374 }
375
376 # we pass exception in ECX to catch handler
377 reg: EXCEPTION {
378         int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
379
380         if (tree->reg1 != X86_ECX)
381                 x86_mov_reg_reg (s->code, tree->reg1, X86_ECX, 4);
382         
383         /* store it so that we can RETHROW it later */
384         x86_mov_membase_reg (s->code, X86_EBP, offset, tree->reg1, 4);
385 }
386
387 stmt: THROW (reg) {
388         gpointer target;
389
390         x86_push_reg (s->code, tree->left->reg1);
391         target = arch_get_throw_exception ();
392         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, target);
393         x86_call_code (s->code, target);
394 }
395
396 stmt: RETHROW {
397         int off = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
398         gpointer target;
399
400         x86_push_membase (s->code, X86_EBP, off);
401         target = arch_get_throw_exception ();
402         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, target);
403         x86_call_code (s->code, target);
404 }
405
406 stmt: HANDLER {
407         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_BB, tree->data.bb);
408         x86_call_imm (s->code, 0); 
409 }
410
411 stmt: ENDFINALLY {
412         x86_ret (s->code);
413 }
414
415 stmt: STIND_I4 (addr, coni4) {
416         switch (tree->left->data.ainfo.amode) {
417
418         case AMImmediate:
419                 x86_mov_mem_imm (s->code, tree->left->data.ainfo.offset, tree->right->data.i, 4);
420                 break;
421                 
422         case AMBase:
423                 x86_mov_membase_imm (s->code, tree->left->data.ainfo.basereg, 
424                                      tree->left->data.ainfo.offset, tree->right->data.i, 4);
425                 break;          
426         case AMIndex:
427                 x86_mov_memindex_imm (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
428                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
429                                       tree->right->data.i, 4);
430                 break;          
431         case AMBaseIndex:
432                 x86_mov_memindex_imm (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
433                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
434                                       tree->right->data.i, 4);
435                 break;          
436         }
437 }
438
439 stmt: STIND_I4 (addr, reg) {
440         PRINT_REG ("STIND_I4", tree->right->reg1);
441
442         switch (tree->left->data.ainfo.amode) {
443
444         case AMImmediate:
445                 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
446                 break;
447                 
448         case AMBase:
449                 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg, 
450                                      tree->left->data.ainfo.offset, tree->right->reg1, 4);
451                 break;          
452         case AMIndex:
453                 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
454                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
455                                       tree->right->reg1, 4);
456                 break;          
457         case AMBaseIndex:
458                 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
459                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
460                                       tree->right->reg1, 4);
461                 break;          
462         }
463 }
464
465 stmt: REMOTE_STIND_I4 (reg, reg) {
466         guint8 *br[2];
467         int treg = X86_EAX;
468         int lreg = tree->left->reg1;
469         int rreg = tree->right->reg1;
470         int offset;
471
472         if (lreg == treg)
473                 treg = X86_EDX;
474
475         if (rreg == treg)
476                 treg = X86_ECX;
477
478         x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
479         x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
480         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
481
482         /* this is a transparent proxy - remote the call */
483
484         /* save value to stack */
485         x86_push_reg (s->code, rreg);
486
487         x86_push_reg (s->code, X86_ESP);
488         x86_push_imm (s->code, tree->data.fi.field);
489         x86_push_imm (s->code, tree->data.fi.klass);
490         x86_push_reg (s->code, lreg);
491         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_store_remote_field);
492         x86_call_code (s->code, 0);
493         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
494
495         br [1] = s->code; x86_jump8 (s->code, 0);
496
497         x86_patch (br [0], s->code);
498         offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) : 
499                 tree->data.fi.field->offset;
500         x86_mov_membase_reg (s->code, lreg, offset, rreg, 4);
501
502         x86_patch (br [1], s->code);
503 }
504
505 stmt: STIND_REF (addr, reg) {
506         PRINT_REG ("STIND_REF", tree->right->reg1);
507
508         switch (tree->left->data.ainfo.amode) {
509
510         case AMImmediate:
511                 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
512                 break;
513                 
514         case AMBase:
515                 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg, 
516                                      tree->left->data.ainfo.offset, tree->right->reg1, 4);
517                 break;          
518         case AMIndex:
519                 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
520                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
521                                       tree->right->reg1, 4);
522                 break;          
523         case AMBaseIndex:
524                 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
525                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
526                                       tree->right->reg1, 4);
527                 break;          
528         }
529 }
530
531 stmt: REMOTE_STIND_REF (reg, reg) {
532         guint8 *br[2];
533         int treg = X86_EAX;
534         int lreg = tree->left->reg1;
535         int rreg = tree->right->reg1;
536         int offset;
537
538         if (lreg == treg)
539                 treg = X86_EDX;
540
541         if (rreg == treg)
542                 treg = X86_ECX;
543
544         x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
545         x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
546         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
547
548         /* this is a transparent proxy - remote the call */
549
550         /* save value to stack */
551         x86_push_reg (s->code, rreg);
552
553         x86_push_reg (s->code, X86_ESP);
554         x86_push_imm (s->code, tree->data.fi.field);
555         x86_push_imm (s->code, tree->data.fi.klass);
556         x86_push_reg (s->code, lreg);
557         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_store_remote_field);
558         x86_call_code (s->code, 0);
559         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
560
561         br [1] = s->code; x86_jump8 (s->code, 0);
562
563         x86_patch (br [0], s->code);
564         offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) : 
565                 tree->data.fi.field->offset;
566         x86_mov_membase_reg (s->code, lreg, offset, rreg, 4);
567
568         x86_patch (br [1], s->code);
569 }
570
571 stmt: STIND_I1 (addr, reg) {
572         PRINT_REG ("STIND_I1", tree->right->reg1);
573
574         switch (tree->left->data.ainfo.amode) {
575
576         case AMImmediate:
577                 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 1);
578                 break;
579                 
580         case AMBase:
581                 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg, 
582                                      tree->left->data.ainfo.offset, tree->right->reg1, 1);
583                 break;          
584         case AMIndex:
585                 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
586                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
587                                       tree->right->reg1, 1);
588                 break;          
589         case AMBaseIndex:
590                 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
591                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
592                                       tree->right->reg1, 1);
593                 break;          
594         }
595 }
596
597 stmt: REMOTE_STIND_I1 (reg, reg) {
598         guint8 *br[2];
599         int treg = X86_EAX;
600         int lreg = tree->left->reg1;
601         int rreg = tree->right->reg1;
602         int offset;
603
604         if (lreg == treg)
605                 treg = X86_EDX;
606
607         if (rreg == treg)
608                 treg = X86_ECX;
609
610         x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
611         x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
612         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
613
614         /* this is a transparent proxy - remote the call */
615
616         /* save value to stack */
617         x86_push_reg (s->code, rreg);
618
619         x86_push_reg (s->code, X86_ESP);
620         x86_push_imm (s->code, tree->data.fi.field);
621         x86_push_imm (s->code, tree->data.fi.klass);
622         x86_push_reg (s->code, lreg);
623         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_store_remote_field);
624         x86_call_code (s->code, 0);
625         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
626
627         br [1] = s->code; x86_jump8 (s->code, 0);
628
629         x86_patch (br [0], s->code);
630         offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) : 
631                 tree->data.fi.field->offset;
632         x86_mov_membase_reg (s->code, lreg, offset, rreg, 1);
633
634         x86_patch (br [1], s->code);
635 }
636
637 stmt: STIND_I2 (addr, reg) {
638         PRINT_REG ("STIND_I2", tree->right->reg1);
639
640         switch (tree->left->data.ainfo.amode) {
641
642         case AMImmediate:
643                 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 2);
644                 break;
645                 
646         case AMBase:
647                 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg, 
648                                      tree->left->data.ainfo.offset, tree->right->reg1, 2);
649                 break;          
650         case AMIndex:
651                 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
652                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
653                                       tree->right->reg1, 2);
654                 break;          
655         case AMBaseIndex:
656                 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
657                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
658                                       tree->right->reg1, 2);
659                 break;          
660         }
661 }
662
663 stmt: REMOTE_STIND_I2 (reg, reg) {
664         guint8 *br[2];
665         int treg = X86_EAX;
666         int lreg = tree->left->reg1;
667         int rreg = tree->right->reg1;
668         int offset;
669
670         if (lreg == treg)
671                 treg = X86_EDX;
672
673         if (rreg == treg)
674                 treg = X86_ECX;
675
676         x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
677         x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
678         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
679
680         /* this is a transparent proxy - remote the call */
681
682         /* save value to stack */
683         x86_push_reg (s->code, rreg);
684
685         x86_push_reg (s->code, X86_ESP);
686         x86_push_imm (s->code, tree->data.fi.field);
687         x86_push_imm (s->code, tree->data.fi.klass);
688         x86_push_reg (s->code, lreg);
689         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_store_remote_field);
690         x86_call_code (s->code, 0);
691         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
692
693         br [1] = s->code; x86_jump8 (s->code, 0);
694
695         x86_patch (br [0], s->code);
696         offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) : 
697                 tree->data.fi.field->offset;
698         x86_mov_membase_reg (s->code, lreg, offset, rreg, 2);
699
700         x86_patch (br [1], s->code);
701 }
702
703 reg: LDIND_I4 (addr) {
704
705         switch (tree->left->data.ainfo.amode) {
706
707         case AMImmediate:
708                 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
709                 break;
710
711         case AMBase:
712                 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
713                                      tree->left->data.ainfo.offset, 4);
714                 break;          
715         case AMIndex:
716                 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
717                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
718                 break;          
719         case AMBaseIndex:
720                 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
721                                       tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg, 
722                                       tree->left->data.ainfo.shift, 4);
723                 break;          
724         }
725
726
727         PRINT_REG ("LDIND_I4", tree->reg1);
728 }
729
730 reg: LDIND_REF (addr) {
731
732         switch (tree->left->data.ainfo.amode) {
733
734         case AMImmediate:
735                 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
736                 break;
737
738         case AMBase:
739                 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
740                                      tree->left->data.ainfo.offset, 4);
741                 break;          
742         case AMIndex:
743                 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
744                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
745                 break;          
746         case AMBaseIndex:
747                 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
748                                       tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg, 
749                                       tree->left->data.ainfo.shift, 4);
750                 break;          
751         }
752
753
754         PRINT_REG ("LDIND_REF", tree->reg1);
755 }
756
757 reg: LDIND_I1 (addr) {
758         switch (tree->left->data.ainfo.amode) {
759
760         case AMImmediate:
761                 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, FALSE);
762                 break;
763
764         case AMBase:
765                 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
766                                    tree->left->data.ainfo.offset, TRUE, FALSE);
767                 break;          
768         case AMIndex:
769                 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
770                                     tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, TRUE, FALSE);
771                 break;          
772         case AMBaseIndex:
773                 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
774                                     tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg, 
775                                     tree->left->data.ainfo.shift, TRUE, FALSE);
776                 break;          
777         }
778
779         PRINT_REG ("LDIND_I1", tree->reg1);
780 }
781
782 reg: LDIND_U1 (addr) {
783         switch (tree->left->data.ainfo.amode) {
784
785         case AMImmediate:
786                 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, FALSE);
787                 break;
788
789         case AMBase:
790                 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
791                                    tree->left->data.ainfo.offset, FALSE, FALSE);
792                 break;          
793         case AMIndex:
794                 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
795                                     tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, FALSE, FALSE);
796                 break;          
797         case AMBaseIndex:
798                 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
799                                     tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg, 
800                                     tree->left->data.ainfo.shift, FALSE, FALSE);
801                 break;          
802         }
803
804         PRINT_REG ("LDIND_U1", tree->reg1);
805 }
806
807 reg: LDIND_I2 (addr) {
808         switch (tree->left->data.ainfo.amode) {
809
810         case AMImmediate:
811                 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, TRUE);
812                 break;
813
814         case AMBase:
815                 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
816                                    tree->left->data.ainfo.offset, TRUE, TRUE);
817                 break;          
818         case AMIndex:
819                 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
820                                     tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, TRUE, TRUE);
821                 break;          
822         case AMBaseIndex:
823                 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
824                                     tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg, 
825                                     tree->left->data.ainfo.shift, TRUE, TRUE);
826                 break;          
827         }
828
829         PRINT_REG ("LDIND_U2", tree->reg1);
830 }
831
832 reg: LDIND_U2 (addr) {
833         switch (tree->left->data.ainfo.amode) {
834
835         case AMImmediate:
836                 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, TRUE);
837                 break;
838
839         case AMBase:
840                 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
841                                    tree->left->data.ainfo.offset, FALSE, TRUE);
842                 break;          
843         case AMIndex:
844                 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
845                                     tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, FALSE, TRUE);
846                 break;          
847         case AMBaseIndex:
848                 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
849                                     tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg, 
850                                     tree->left->data.ainfo.shift, FALSE, TRUE);
851                 break;          
852         }
853
854         PRINT_REG ("LDIND_U2", tree->reg1);
855 }
856
857 reg: LDIND_U4 (addr) {
858         switch (tree->left->data.ainfo.amode) {
859
860         case AMImmediate:
861                 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
862                 break;
863
864         case AMBase:
865                 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
866                                      tree->left->data.ainfo.offset, 4);
867                 break;          
868         case AMIndex:
869                 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
870                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
871                 break;          
872         case AMBaseIndex:
873                 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
874                                       tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg, 
875                                       tree->left->data.ainfo.shift, 4);
876                 break;          
877         }
878
879         PRINT_REG ("LDIND_U4", tree->reg1);
880 }
881
882 reg: REMOTE_LDFLDA (reg) {
883         guint8 *br[2];
884         int treg = X86_EAX;
885         int lreg = tree->left->reg1;
886
887         if (lreg == X86_EAX)
888                 treg = X86_EDX;
889
890         if (tree->reg1 != treg)
891                 x86_push_reg (s->code, treg);
892
893         x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
894         x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
895         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
896
897         /* this is a transparent proxy - remote the call */
898         if (treg != X86_EAX)
899                 x86_push_reg (s->code, X86_EAX);
900         if (treg != X86_EDX)
901                 x86_push_reg (s->code, X86_EDX);
902         x86_push_reg (s->code, X86_ECX);
903
904         x86_push_reg (s->code, X86_ESP);
905         x86_push_imm (s->code, tree->data.fi.field);
906         x86_push_imm (s->code, tree->data.fi.klass);
907         x86_push_reg (s->code, lreg);
908         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_load_remote_field);
909         x86_call_code (s->code, 0);
910         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
911
912         if (treg != X86_EAX)
913                 x86_mov_reg_reg (s->code, treg, X86_EAX, 4);
914
915         x86_pop_reg (s->code, X86_ECX);
916         if (treg != X86_EDX)
917                 x86_pop_reg (s->code, X86_EDX);
918         if (treg != X86_EAX)
919                 x86_pop_reg (s->code, X86_EAX);
920
921         x86_mov_reg_reg (s->code, tree->reg1, treg, 4);
922
923         br [1] = s->code; x86_jump8 (s->code, 0);
924         
925         x86_patch (br [0], s->code);
926         if (tree->data.fi.klass->valuetype)
927                 x86_lea_membase (s->code, tree->reg1, lreg, 
928                                  tree->data.fi.field->offset - sizeof (MonoObject));
929         else 
930                 x86_lea_membase (s->code, tree->reg1, lreg, tree->data.fi.field->offset);
931
932         x86_patch (br [1], s->code);
933
934         if (tree->reg1 != treg)
935                 x86_pop_reg (s->code, treg);
936 }
937
938 reg: ADDR_L 5 {
939         int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;  
940
941         x86_lea_membase (s->code, tree->reg1, X86_EBP, offset);
942         
943         PRINT_REG ("ADDR_L",  tree->reg1);
944 }
945
946
947 reg: ADDR_G 5 {
948         x86_mov_reg_imm (s->code, tree->reg1, tree->data.p);
949 }
950
951 reg: CONV_I1 (reg) {
952         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
953 }
954
955 reg: CONV_U1 (reg) {
956         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
957 }
958
959 reg: CONV_I2 (reg) {
960         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
961 }
962
963 reg: CONV_U2 (reg) {
964         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
965 }
966
967 # warning: this chain rule requires a register
968 reg: coni4 1 {
969         x86_mov_reg_imm (s->code, tree->reg1, tree->data.i);
970 }
971
972 reg: CONV_I4 (reg) {
973         if (tree->reg1 != tree->left->reg1)
974                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
975         PRINT_REG ("CONV_I4", tree->left->reg1);
976
977
978 reg: CONV_U4 (reg) {
979         if (tree->reg1 != tree->left->reg1)
980                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
981         PRINT_REG ("CONV_U4", tree->left->reg1);
982
983
984 reg: CONV_OVF_I4 (reg) {
985         if (tree->reg1 != tree->left->reg1)
986                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
987         PRINT_REG ("CONV_OVF_I4", tree->left->reg1);
988 }
989
990 reg: CONV_OVF_U4 (reg) {
991         /* Keep in sync with CONV_OVF_I4_UN below, they are the same on 32-bit machines */
992         x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
993         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
994         if (tree->reg1 != tree->left->reg1)
995                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
996 }
997
998 reg: CONV_OVF_I4_UN (reg) {
999         /* Keep in sync with CONV_OVF_U4 above, they are the same on 32-bit machines */
1000         x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
1001         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1002         if (tree->reg1 != tree->left->reg1)
1003                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1004 }
1005
1006 reg: CONV_OVF_I1 (reg) {
1007         /* probe value to be within -128 to 127 */
1008         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 127);
1009         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, TRUE, "OverflowException");      
1010         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, -128);
1011         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GT, TRUE, "OverflowException");      
1012         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
1013 }
1014
1015 reg: CONV_OVF_I1_UN (reg) {
1016         /* probe values between 0 to 128 */
1017         x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff80);
1018         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");     
1019         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
1020 }
1021
1022 reg: CONV_OVF_U1 (reg) {
1023         /* Keep in sync with CONV_OVF_U1_UN routine below, they are the same on 32-bit machines */
1024         /* probe value to be within 0 to 255 */
1025         x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff00);
1026         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");     
1027         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
1028 }
1029
1030 reg: CONV_OVF_U1_UN (reg) {
1031         /* Keep in sync with CONV_OVF_U1 routine above, they are the same on 32-bit machines */
1032         /* probe value to be within 0 to 255 */
1033         x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff00);
1034         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");     
1035         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
1036 }
1037
1038 reg: CONV_OVF_I2 (reg) {        
1039         /* Probe value to be within -32768 and 32767 */
1040         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 32767);
1041         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, TRUE, "OverflowException");      
1042         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, -32768);
1043         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GE, TRUE, "OverflowException");      
1044         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
1045 }
1046
1047 reg: CONV_OVF_U2 (reg) {
1048         /* Keep in sync with CONV_OVF_U2_UN below, they are the same on 32-bit machines */
1049         /* Probe value to be within 0 and 65535 */
1050         x86_test_reg_imm (s->code, tree->left->reg1, 0xffff0000);
1051         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");      
1052         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
1053 }
1054
1055 reg: CONV_OVF_U2_UN (reg) {
1056         /* Keep in sync with CONV_OVF_U2 above, they are the same on 32-bit machines */
1057         /* Probe value to be within 0 and 65535 */
1058         x86_test_reg_imm (s->code, tree->left->reg1, 0xffff0000);
1059         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");     
1060         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
1061 }
1062
1063 reg: CONV_OVF_I2_UN (reg) {
1064         /* Convert uint value into short, value within 0 and 32767 */
1065         x86_test_reg_imm (s->code, tree->left->reg1, 0xffff8000);
1066         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");     
1067         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
1068 }
1069
1070 reg: MUL (reg, reg) {
1071         x86_imul_reg_reg (s->code, tree->left->reg1, tree->right->reg1);
1072
1073         if (tree->reg1 != tree->left->reg1)
1074                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1075 }
1076
1077 reg: MUL_OVF (reg, reg) {
1078         x86_imul_reg_reg (s->code, tree->left->reg1, tree->right->reg1);
1079         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");      
1080
1081         if (tree->reg1 != tree->left->reg1)
1082                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1083 }
1084
1085 reg: MUL_OVF_UN (reg, reg) {
1086         mono_assert (tree->right->reg1 != X86_EAX);
1087         
1088         if (tree->left->reg1 != X86_EAX)
1089                 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1090
1091         x86_mul_reg (s->code, tree->right->reg1, FALSE);
1092         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
1093
1094         mono_assert (tree->reg1 == X86_EAX &&
1095                      tree->reg2 == X86_EDX);
1096 }
1097
1098 reg: DIV (reg, reg) {
1099         mono_assert (tree->right->reg1 != X86_EAX);
1100
1101         if (tree->left->reg1 != X86_EAX)
1102                 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1103
1104         x86_cdq (s->code);
1105         x86_div_reg (s->code, tree->right->reg1, TRUE);
1106
1107         mono_assert (tree->reg1 == X86_EAX &&
1108                      tree->reg2 == X86_EDX);
1109 }
1110
1111 reg: DIV_UN (reg, reg) {
1112         mono_assert (tree->right->reg1 != X86_EAX);
1113
1114         if (tree->left->reg1 != X86_EAX)
1115                 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1116
1117         x86_mov_reg_imm (s->code, X86_EDX, 0);
1118         x86_div_reg (s->code, tree->right->reg1, FALSE);
1119
1120         mono_assert (tree->reg1 == X86_EAX &&
1121                      tree->reg2 == X86_EDX);
1122 }
1123
1124 reg: REM (reg, reg) {
1125         mono_assert (tree->right->reg1 != X86_EAX);
1126         mono_assert (tree->right->reg1 != X86_EDX);
1127
1128         if (tree->left->reg1 != X86_EAX)
1129                 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1130
1131         /* sign extend to 64bit in EAX/EDX */
1132         x86_cdq (s->code);
1133         x86_div_reg (s->code, tree->right->reg1, TRUE);
1134         x86_mov_reg_reg (s->code, X86_EAX, X86_EDX, 4);
1135
1136         mono_assert (tree->reg1 == X86_EAX &&
1137                      tree->reg2 == X86_EDX);
1138 }
1139
1140 reg: REM_UN (reg, reg) {
1141         mono_assert (tree->right->reg1 != X86_EAX);
1142         mono_assert (tree->right->reg1 != X86_EDX);
1143
1144         if (tree->left->reg1 != X86_EAX)
1145                 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1146
1147         /* zero extend to 64bit in EAX/EDX */
1148         x86_mov_reg_imm (s->code, X86_EDX, 0); 
1149         x86_div_reg (s->code, tree->right->reg1, FALSE);
1150         x86_mov_reg_reg (s->code, X86_EAX, X86_EDX, 4);
1151
1152         mono_assert (tree->reg1 == X86_EAX &&
1153                      tree->reg2 == X86_EDX);
1154 }
1155
1156 reg: ADD (reg, coni4) "MB_USE_OPT1(0)" {
1157         if (tree->right->data.i == 1)
1158                 x86_inc_reg (s->code, tree->left->reg1);
1159         else 
1160                 x86_alu_reg_imm (s->code, X86_ADD, tree->left->reg1, tree->right->data.i);
1161
1162         if (tree->reg1 != tree->left->reg1)
1163                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1164
1165 }
1166
1167 reg: ADD (reg, reg) {
1168         x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
1169
1170         if (tree->reg1 != tree->left->reg1)
1171                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1172 }
1173
1174 reg: ADD_OVF (reg, reg) {
1175         x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
1176         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");      
1177
1178         if (tree->reg1 != tree->left->reg1)
1179                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1180 }
1181
1182 reg: ADD_OVF_UN (reg, reg) {
1183         x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
1184         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");     
1185
1186         if (tree->reg1 != tree->left->reg1)
1187                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1188 }
1189
1190 reg: SUB (reg, coni4) "MB_USE_OPT1(0)" {
1191         if (tree->right->data.i == 1)
1192                 x86_dec_reg (s->code, tree->left->reg1);
1193         else
1194                 x86_alu_reg_imm (s->code, X86_SUB, tree->left->reg1, tree->right->data.i);
1195
1196         if (tree->reg1 != tree->left->reg1)
1197                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1198 }
1199
1200 reg: SUB (reg, reg) {
1201         x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
1202
1203         if (tree->reg1 != tree->left->reg1)
1204                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1205 }
1206
1207 reg: SUB_OVF (reg, reg) {
1208         x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
1209         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");      
1210
1211         if (tree->reg1 != tree->left->reg1)
1212                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1213 }
1214
1215 reg: SUB_OVF_UN (reg, reg) {
1216         x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
1217         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");     
1218
1219         if (tree->reg1 != tree->left->reg1)
1220                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1221 }
1222
1223 reg: CEQ (reg, coni4) "MB_USE_OPT1(0)" {
1224         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1225         x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
1226         x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
1227 }
1228
1229 reg: CEQ (reg, reg) {
1230         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1231         x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
1232         x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
1233 }
1234
1235 reg: CGT (reg, reg) {
1236         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1237         x86_set_reg (s->code, X86_CC_GT, tree->reg1, TRUE);
1238         x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
1239 }
1240
1241 reg: CGT_UN (reg, reg) {
1242         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1243         x86_set_reg (s->code, X86_CC_GT, tree->reg1, FALSE);
1244         x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
1245 }
1246
1247 reg: CLT (reg, reg) {
1248         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1249         x86_set_reg (s->code, X86_CC_LT, tree->reg1, TRUE);
1250         x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
1251 }
1252
1253 reg: CLT_UN (reg, reg) {
1254         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1255         x86_set_reg (s->code, X86_CC_LT, tree->reg1, FALSE);
1256         x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
1257 }
1258
1259 reg: AND (reg, reg) {
1260         x86_alu_reg_reg (s->code, X86_AND, tree->left->reg1, tree->right->reg1);
1261
1262         if (tree->reg1 != tree->left->reg1)
1263                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1264 }
1265
1266 reg: OR (reg, reg) {
1267         x86_alu_reg_reg (s->code, X86_OR, tree->left->reg1, tree->right->reg1);
1268
1269         if (tree->reg1 != tree->left->reg1)
1270                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1271 }
1272
1273 reg: XOR (reg, reg) {
1274         x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->right->reg1);
1275
1276         if (tree->reg1 != tree->left->reg1)
1277                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1278 }
1279
1280 reg: NEG (reg) {
1281         x86_neg_reg (s->code, tree->left->reg1);
1282
1283         if (tree->reg1 != tree->left->reg1)
1284                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1285 }
1286
1287 reg: NOT (reg) {
1288         x86_not_reg (s->code, tree->left->reg1);
1289
1290         if (tree->reg1 != tree->left->reg1)
1291                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1292 }
1293
1294 reg: SHL (reg, coni4) {
1295         x86_shift_reg_imm (s->code, X86_SHL, tree->left->reg1, tree->right->data.i);
1296
1297         if (tree->reg1 != tree->left->reg1)
1298                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1299 }
1300
1301 reg: SHL (reg, reg) {
1302         if (tree->right->reg1 != X86_ECX)
1303                 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1304         x86_shift_reg (s->code, X86_SHL, tree->left->reg1);
1305
1306         if (tree->reg1 != tree->left->reg1)
1307                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1308
1309         mono_assert (tree->reg1 != X86_ECX &&
1310                   tree->left->reg1 != X86_ECX);
1311 }
1312
1313 reg: SHR (reg, coni4) {
1314         x86_shift_reg_imm (s->code, X86_SAR, tree->left->reg1, tree->right->data.i);
1315
1316         if (tree->reg1 != tree->left->reg1)
1317                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1318 }
1319
1320 reg: SHR (reg, reg) {
1321         if (tree->right->reg1 != X86_ECX)
1322                 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1323         x86_shift_reg (s->code, X86_SAR, tree->left->reg1);
1324
1325         if (tree->reg1 != tree->left->reg1)
1326                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1327
1328         mono_assert (tree->reg1 != X86_ECX &&
1329                   tree->left->reg1 != X86_ECX);
1330 }
1331
1332 reg: SHR_UN (reg, coni4) {
1333         x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg1, tree->right->data.i);
1334
1335         if (tree->reg1 != tree->left->reg1)
1336                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1337 }
1338
1339 reg: SHR_UN (reg, reg) {
1340         if (tree->right->reg1 != X86_ECX)
1341                 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1342         x86_shift_reg (s->code, X86_SHR, tree->left->reg1);
1343
1344         if (tree->reg1 != tree->left->reg1)
1345                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1346
1347         mono_assert (tree->reg1 != X86_ECX &&
1348                   tree->left->reg1 != X86_ECX);
1349 }
1350
1351 reg: LDSFLDA (coni4) {
1352         if (tree->reg1 != X86_EAX)
1353                 x86_push_reg (s->code, X86_EAX);
1354         x86_push_reg (s->code, X86_ECX);
1355         x86_push_reg (s->code, X86_EDX);
1356
1357         x86_push_imm (s->code, tree->left->data.i);
1358         x86_push_imm (s->code, tree->data.klass);
1359         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_ldsflda);
1360         x86_call_code (s->code, 0);
1361         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1362         
1363         x86_pop_reg (s->code, X86_EDX);
1364         x86_pop_reg (s->code, X86_ECX);
1365         if (tree->reg1 != X86_EAX) {
1366                 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1367                 x86_pop_reg (s->code, X86_EAX);
1368         }
1369 }
1370
1371 # array support
1372 reg: LDLEN (reg) {      
1373         x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
1374         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NE, TRUE, "NullReferenceException");
1375
1376         x86_mov_reg_membase (s->code, tree->reg1, tree->left->reg1,  
1377                              G_STRUCT_OFFSET (MonoArray, max_length), 4);
1378 }
1379
1380 reg: LDELEMA (reg, reg) {
1381         x86_alu_reg_membase (s->code, X86_CMP, tree->right->reg1, tree->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length));
1382         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LT, FALSE, "IndexOutOfRangeException");
1383
1384         if (tree->data.i == 1 || tree->data.i == 2 || 
1385             tree->data.i == 4 || tree->data.i == 8) {
1386                 static int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
1387                 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 
1388                                   G_STRUCT_OFFSET (MonoArray, vector), tree->right->reg1, 
1389                                   fast_log2 [tree->data.i]);
1390         } else {
1391                 x86_imul_reg_reg_imm (s->code, tree->right->reg1, tree->right->reg1, tree->data.i);
1392                 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
1393                 x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, G_STRUCT_OFFSET (MonoArray, vector));
1394         }
1395 }
1396
1397 reg: LDSTR {
1398         if (tree->reg1 != X86_EAX)
1399                 x86_push_reg (s->code, X86_EAX);
1400         x86_push_reg (s->code, X86_ECX);
1401         x86_push_reg (s->code, X86_EDX);
1402
1403         x86_push_imm (s->code, tree->data.p);
1404         x86_push_imm (s->code, s->method->klass->image);
1405         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_ldstr_wrapper);
1406         x86_call_code (s->code, 0);
1407         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1408
1409         x86_pop_reg (s->code, X86_EDX);
1410         x86_pop_reg (s->code, X86_ECX);
1411         if (tree->reg1 != X86_EAX) {
1412                 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1413                 x86_pop_reg (s->code, X86_EAX);
1414         }
1415
1416         PRINT_REG ("LDSTR", tree->reg1);        
1417 }
1418
1419 reg: NEWARR (reg) {
1420         if (tree->reg1 != X86_EAX)
1421                 x86_push_reg (s->code, X86_EAX);
1422         x86_push_reg (s->code, X86_ECX);
1423         x86_push_reg (s->code, X86_EDX);
1424
1425         x86_push_reg (s->code, tree->left->reg1);
1426         x86_push_imm (s->code, tree->data.p);
1427         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_array_new_wrapper);
1428         x86_call_code (s->code, 0);
1429         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer) + 4);
1430
1431         x86_pop_reg (s->code, X86_EDX);
1432         x86_pop_reg (s->code, X86_ECX);
1433         if (tree->reg1 != X86_EAX) {
1434                 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1435                 x86_pop_reg (s->code, X86_EAX);
1436         }
1437
1438         PRINT_REG ("NEWARR", tree->reg1);
1439 }
1440
1441 reg: NEWARR_SPEC (reg) {
1442         if (tree->reg1 != X86_EAX)
1443                 x86_push_reg (s->code, X86_EAX);
1444         x86_push_reg (s->code, X86_ECX);
1445         x86_push_reg (s->code, X86_EDX);
1446
1447         x86_push_reg (s->code, tree->left->reg1);
1448         x86_push_imm (s->code, tree->data.p);
1449         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_array_new_specific);
1450         x86_call_code (s->code, 0);
1451         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer) + 4);
1452
1453         x86_pop_reg (s->code, X86_EDX);
1454         x86_pop_reg (s->code, X86_ECX);
1455         if (tree->reg1 != X86_EAX) {
1456                 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1457                 x86_pop_reg (s->code, X86_EAX);
1458         }
1459
1460         PRINT_REG ("NEWARR_SPEC", tree->reg1);
1461 }
1462
1463 reg: NEWOBJ {
1464         if (tree->reg1 != X86_EAX)
1465                 x86_push_reg (s->code, X86_EAX);
1466         x86_push_reg (s->code, X86_ECX);
1467         x86_push_reg (s->code, X86_EDX);
1468
1469         x86_push_imm (s->code, tree->data.klass);
1470         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_object_new_wrapper);
1471         x86_call_code (s->code, 0);
1472         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
1473
1474         x86_pop_reg (s->code, X86_EDX);
1475         x86_pop_reg (s->code, X86_ECX);
1476         if (tree->reg1 != X86_EAX) {
1477                 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1478                 x86_pop_reg (s->code, X86_EAX);
1479         }
1480         PRINT_REG ("NEWOBJ", tree->reg1);
1481 }
1482
1483 reg: NEWOBJ_SPEC {
1484         if (tree->reg1 != X86_EAX)
1485                 x86_push_reg (s->code, X86_EAX);
1486         x86_push_reg (s->code, X86_ECX);
1487         x86_push_reg (s->code, X86_EDX);
1488
1489         x86_push_imm (s->code, tree->data.p);
1490         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_object_new_specific);
1491         x86_call_code (s->code, 0);
1492         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
1493
1494         x86_pop_reg (s->code, X86_EDX);
1495         x86_pop_reg (s->code, X86_ECX);
1496         if (tree->reg1 != X86_EAX) {
1497                 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1498                 x86_pop_reg (s->code, X86_EAX);
1499         }
1500         PRINT_REG ("NEWOBJ_SPEC", tree->reg1);
1501 }
1502
1503 reg: NEWSTRUCT {
1504         int size = tree->data.i;        
1505         int sa;
1506         
1507         mono_assert (size > 0);
1508
1509         sa = size + 3;
1510         sa &= ~3;
1511
1512         x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);
1513         x86_mov_reg_reg (s->code, tree->reg1, X86_ESP, 4);
1514 }
1515
1516 reg: UNBOX (reg) {
1517         if (tree->reg1 != tree->left->reg1)
1518                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1519
1520         x86_test_reg_reg (s->code, tree->reg1, tree->reg1);
1521         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NE, TRUE, "NullReferenceException"); 
1522
1523         x86_push_reg (s->code, tree->reg1);
1524         x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, 0, 4); 
1525         x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, 0, 4); 
1526         x86_alu_membase_imm (s->code, X86_CMP, tree->reg1, 
1527                              G_STRUCT_OFFSET (MonoClass, element_class), ((int)(tree->data.klass->element_class)));
1528         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "InvalidCastException");
1529         x86_pop_reg (s->code, tree->reg1);
1530         x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, sizeof (MonoObject));
1531 }
1532
1533 reg: CASTCLASS (reg) {
1534         MonoClass *klass = tree->data.klass;
1535         guint8 *br [2];
1536         int lreg = tree->left->reg1;
1537         
1538         x86_push_reg (s->code, lreg);
1539         x86_test_reg_reg (s->code, lreg, lreg);
1540         br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
1541
1542         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1543                 /* lreg = obj->vtable */
1544                 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1545
1546                 x86_alu_membase_imm (s->code, X86_CMP, lreg, G_STRUCT_OFFSET (MonoVTable, max_interface_id), 
1547                                      klass->interface_id);
1548                 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GE, FALSE, "InvalidCastException");
1549                 /* lreg = obj->vtable->interface_offsets */
1550                 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
1551                 x86_alu_membase_imm (s->code, X86_CMP, lreg, klass->interface_id << 2, 0);
1552                 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NE, FALSE, "InvalidCastException");
1553         } else {
1554
1555                 /* lreg = obj->vtable */
1556                 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1557                 /* lreg = obj->vtable->klass */
1558                 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1559
1560                 if (klass->rank) {
1561
1562                         x86_alu_membase_imm (s->code, X86_CMP, lreg, G_STRUCT_OFFSET (MonoClass, rank), klass->rank);
1563                         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "InvalidCastException");
1564                         x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, element_class), 4);
1565                         x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, baseval), 4);
1566                         x86_alu_reg_mem (s->code, X86_SUB, lreg, &klass->element_class->baseval);
1567                         x86_alu_reg_mem (s->code, X86_CMP, lreg, &klass->element_class->diffval);
1568                         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, FALSE, "InvalidCastException");
1569
1570                 } else {
1571
1572                         if (klass->marshalbyref) {
1573                                 /* check for transparent_proxy */               
1574                                 x86_alu_reg_imm (s->code, X86_CMP, lreg, (int)mono_defaults.transparent_proxy_class);
1575                                 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
1576                 
1577                                 /* lreg = obj */
1578                                 x86_mov_reg_membase (s->code, lreg, X86_ESP, 0, 4);
1579                                 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoTransparentProxy, 
1580                                                                                            klass), 4);
1581
1582                                 x86_patch (br [1], s->code);
1583                         }
1584
1585                         x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, baseval), 4);
1586                         x86_alu_reg_mem (s->code, X86_SUB, lreg, &klass->baseval);
1587                         x86_alu_reg_mem (s->code, X86_CMP, lreg, &klass->diffval);
1588                         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, FALSE, "InvalidCastException");          
1589                 }
1590         }
1591
1592         x86_patch (br [0], s->code);
1593         x86_pop_reg (s->code, tree->reg1);
1594 }
1595
1596 reg: ISINST (reg) {
1597         MonoClass *klass = tree->data.klass;
1598         guint8 *br [3];
1599         int lreg = tree->left->reg1;
1600         
1601         x86_push_reg (s->code, lreg);
1602         x86_test_reg_reg (s->code, lreg, lreg);
1603         br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
1604
1605         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1606                 /* lreg = obj->vtable */
1607                 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1608
1609                 x86_alu_membase_imm (s->code, X86_CMP, lreg, G_STRUCT_OFFSET (MonoVTable, max_interface_id), 
1610                                      klass->interface_id);
1611                 br [1] = s->code; x86_branch8 (s->code, X86_CC_LT, 0, FALSE);
1612                 /* lreg = obj->vtable->interface_offsets */
1613                 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
1614                 x86_alu_membase_imm (s->code, X86_CMP, lreg, klass->interface_id << 2, 0);
1615                 br [2] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
1616                 x86_patch (br [1], s->code);
1617                 x86_mov_membase_imm (s->code, X86_ESP, 0, 0, 4);
1618                 x86_patch (br [2], s->code);
1619
1620         } else {
1621
1622                 /* lreg = obj->vtable */
1623                 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1624                 /* lreg = obj->vtable->klass */
1625                 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1626
1627                 if (klass->rank) {
1628
1629                         x86_alu_membase_imm (s->code, X86_CMP, lreg, G_STRUCT_OFFSET (MonoClass, rank), klass->rank);
1630                         br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
1631                         x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, element_class), 4);
1632                         x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, baseval), 4);
1633                         x86_alu_reg_mem (s->code, X86_SUB, lreg, &klass->element_class->baseval);
1634                         x86_alu_reg_mem (s->code, X86_CMP, lreg, &klass->element_class->diffval);
1635                         br [2] = s->code; x86_branch8 (s->code, X86_CC_LE, 0, FALSE);
1636                         x86_patch (br [1], s->code);
1637                         x86_mov_membase_imm (s->code, X86_ESP, 0, 0, 4);
1638                         x86_patch (br [2], s->code);
1639
1640                 } else {
1641
1642                         if (klass->marshalbyref) {
1643                                 /* check for transparent_proxy */               
1644                                 x86_alu_reg_imm (s->code, X86_CMP, lreg, (int)mono_defaults.transparent_proxy_class);
1645                                 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
1646                 
1647                                 /* lreg = obj */
1648                                 x86_mov_reg_membase (s->code, lreg, X86_ESP, 0, 4);
1649                                 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoTransparentProxy, 
1650                                                                                            klass), 4);
1651                                 x86_patch (br [1], s->code);
1652                         }
1653
1654                         x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, baseval), 4);
1655                         x86_alu_reg_mem (s->code, X86_SUB, lreg, &klass->baseval);
1656                         x86_alu_reg_mem (s->code, X86_CMP, lreg, &klass->diffval);
1657                         br [2] = s->code; x86_branch8 (s->code, X86_CC_LE, 0, FALSE);
1658                         x86_mov_membase_imm (s->code, X86_ESP, 0, 0, 4);
1659                         x86_patch (br [2], s->code);
1660                 }
1661         }
1662
1663         x86_patch (br [0], s->code);
1664         x86_pop_reg (s->code, tree->reg1);
1665 }
1666
1667 stmt: INITOBJ (reg) {
1668         int i, j;
1669
1670         i = tree->data.i;
1671
1672         if (i == 1 || i == 2 || i == 4) {
1673                 x86_mov_membase_imm (s->code, tree->left->reg1, 0, 0, i);
1674                 return;
1675         }
1676
1677         i = tree->data.i / 4;
1678         j = tree->data.i % 4;
1679
1680         x86_push_reg (s->code, X86_EAX);
1681         
1682         if (tree->left->reg1 != X86_EDI) {
1683                 x86_push_reg (s->code, X86_EDI);
1684                 x86_mov_reg_reg (s->code, X86_EDI, tree->left->reg1, 4);
1685         }
1686
1687         if (i) {
1688                 x86_push_reg (s->code, X86_ECX);
1689                 x86_alu_reg_reg (s->code, X86_XOR, X86_EAX, X86_EAX);
1690                 x86_mov_reg_imm (s->code, X86_ECX, i);
1691                 x86_cld (s->code);
1692                 x86_prefix (s->code, X86_REP_PREFIX);
1693                 x86_stosl (s->code);
1694                 x86_pop_reg (s->code, X86_ECX);
1695
1696                 for (i = 0; i < j; i++)
1697                         x86_stosb (s->code);
1698
1699         } else {
1700                 g_assert (j == 3);
1701                 x86_mov_membase_imm (s->code, X86_EDI, 0, 0, 2);
1702                 x86_mov_membase_imm (s->code, X86_EDI, 2, 0, 1);
1703         }
1704
1705
1706
1707         if (tree->left->reg1 != X86_EDI)
1708                 x86_pop_reg (s->code, X86_EDI);
1709         
1710         x86_pop_reg (s->code, X86_EAX);
1711 }
1712
1713 stmt: NOP
1714
1715 stmt: POP (reg)
1716
1717 stmt: BR {
1718         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_BB, tree->data.bb);
1719         x86_jump32 (s->code, 0); 
1720 }
1721
1722 stmt: BLT (reg, reg) 1 {
1723         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1724         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1725         x86_branch32 (s->code, X86_CC_LT, 0, TRUE); 
1726 }
1727
1728 stmt: BLT (reg, coni4) "MB_USE_OPT1(0)" {
1729         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1730         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1731         x86_branch32 (s->code, X86_CC_LT, 0, TRUE); 
1732 }
1733
1734 stmt: BLT_UN (reg, reg) 1 {
1735         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1736         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1737         x86_branch32 (s->code, X86_CC_LT, 0, FALSE); 
1738 }
1739
1740 stmt: BLT_UN (reg, coni4) "MB_USE_OPT1(0)" {
1741         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1742         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1743         x86_branch32 (s->code, X86_CC_LT, 0, FALSE); 
1744 }
1745
1746 stmt: BGT (reg, reg) 1 {
1747         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1748         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1749         x86_branch32 (s->code, X86_CC_GT, 0, TRUE); 
1750 }
1751
1752 stmt: BGT (reg, coni4) "MB_USE_OPT1(0)" {
1753         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1754         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1755         x86_branch32 (s->code, X86_CC_GT, 0, TRUE); 
1756 }
1757
1758 stmt: BGT_UN (reg, reg) 1 {
1759         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1760         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1761         x86_branch32 (s->code, X86_CC_GT, 0, FALSE); 
1762 }
1763
1764 stmt: BGT_UN (reg, coni4) "MB_USE_OPT1(0)" {
1765         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1766         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1767         x86_branch32 (s->code, X86_CC_GT, 0, FALSE); 
1768 }
1769
1770 stmt: BEQ (reg, coni4) "MB_USE_OPT1(0)" {
1771         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1772         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1773         x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
1774 }
1775
1776 stmt: BEQ (reg, reg) 1 {
1777         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1778         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1779         x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
1780 }
1781
1782 stmt: BNE_UN (reg, reg) 1 {
1783         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1784         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1785         x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
1786 }
1787
1788 stmt: BNE_UN (reg, coni4) "MB_USE_OPT1(0)" {
1789         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1790         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1791         x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
1792 }
1793
1794 stmt: BGE (reg, reg) 1 {
1795         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1796         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1797         x86_branch32 (s->code, X86_CC_GE, 0, TRUE);
1798 }
1799
1800 stmt: BGE (reg, coni4) "MB_USE_OPT1(0)" {
1801         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1802         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1803         x86_branch32 (s->code, X86_CC_GE, 0, TRUE);
1804 }
1805
1806 stmt: BGE_UN (reg, reg) 1 {
1807         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1808         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1809         x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
1810 }
1811
1812 stmt: BGE_UN (reg, coni4) "MB_USE_OPT1(0)" {
1813         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1814         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1815         x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
1816 }
1817
1818 stmt: BLE (reg, reg) 1 {
1819         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1820         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1821         x86_branch32 (s->code, X86_CC_LE, 0, TRUE);
1822 }
1823
1824 stmt: BLE (reg, coni4) "MB_USE_OPT1(0)" {
1825         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1826         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1827         x86_branch32 (s->code, X86_CC_LE, 0, TRUE);
1828 }
1829
1830 stmt: BLE_UN (reg, reg) 1 {
1831         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1832         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1833         x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
1834 }
1835
1836 stmt: BLE_UN (reg, coni4) "MB_USE_OPT1(0)" {
1837         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1838         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1839         x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
1840 }
1841
1842 stmt: BRTRUE (reg) {
1843         x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
1844         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1845         x86_branch32 (s->code, X86_CC_NE, 0, TRUE);
1846 }
1847
1848 stmt: BRFALSE (reg) {
1849         x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
1850         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1851         x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
1852 }
1853
1854 stmt: BREAK {
1855         x86_breakpoint (s->code);
1856 }
1857
1858 stmt: RET (reg) {
1859         if (tree->left->reg1 != X86_EAX)
1860                 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1861
1862         if (!tree->last_instr) {
1863                 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_EPILOG, NULL);
1864                 x86_jump32 (s->code, 0);      
1865         }
1866 }
1867
1868 stmt: RET_VOID {
1869         if (!tree->last_instr) {
1870                 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_EPILOG, NULL);
1871                 x86_jump32 (s->code, 0);      
1872         } 
1873 }
1874
1875
1876 stmt: ARG_I4 (LDIND_I4 (addr)) {
1877         MBTree *at = tree->left->left;
1878
1879         switch (at->data.ainfo.amode) {
1880
1881         case AMImmediate:
1882                 x86_push_mem (s->code, at->data.ainfo.offset);
1883                 break;
1884
1885         case AMBase:
1886                 x86_push_membase (s->code, at->data.ainfo.basereg, at->data.ainfo.offset);
1887                 break;          
1888         case AMIndex:
1889                 x86_push_memindex (s->code, X86_NOBASEREG, at->data.ainfo.offset,
1890                                    at->data.ainfo.indexreg, at->data.ainfo.shift);
1891                 break;          
1892         case AMBaseIndex:
1893                 x86_push_memindex (s->code, at->data.ainfo.basereg, 
1894                                    at->data.ainfo.offset, at->data.ainfo.indexreg, 
1895                                    at->data.ainfo.shift);
1896                 break;          
1897         }
1898 }
1899
1900 stmt: ARG_I4 (LDIND_U4 (addr)) {
1901         MBTree *at = tree->left->left;
1902
1903         switch (at->data.ainfo.amode) {
1904
1905         case AMImmediate:
1906                 x86_push_mem (s->code, at->data.ainfo.offset);
1907                 break;
1908
1909         case AMBase:
1910                 x86_push_membase (s->code, at->data.ainfo.basereg, at->data.ainfo.offset);
1911                 break;          
1912         case AMIndex:
1913                 x86_push_memindex (s->code, X86_NOBASEREG, at->data.ainfo.offset,
1914                                    at->data.ainfo.indexreg, at->data.ainfo.shift);
1915                 break;          
1916         case AMBaseIndex:
1917                 x86_push_memindex (s->code, at->data.ainfo.basereg, 
1918                                    at->data.ainfo.offset, at->data.ainfo.indexreg, 
1919                                    at->data.ainfo.shift);
1920                 break;          
1921         }
1922 }
1923
1924 stmt: ARG_I4 (reg) {
1925         x86_push_reg (s->code, tree->left->reg1);
1926         PRINT_REG ("ARG_I4",  tree->left->reg1);
1927 }
1928
1929 # fixme: we must free the allocated strings somewhere
1930 stmt: ARG_STRING (reg) {
1931         x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
1932         x86_push_reg (s->code, X86_EAX);
1933         x86_push_reg (s->code, X86_ECX);
1934         x86_push_reg (s->code, X86_EDX);
1935
1936         x86_push_reg (s->code, tree->left->reg1);
1937         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_string_to_utf8);
1938         x86_call_code (s->code, 0);
1939         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
1940         
1941         x86_mov_membase_reg (s->code, X86_ESP, 12, X86_EAX, 4);
1942
1943         x86_pop_reg (s->code, X86_EDX);
1944         x86_pop_reg (s->code, X86_ECX);
1945         x86_pop_reg (s->code, X86_EAX);
1946 }
1947
1948 stmt: ARG_I4 (ADDR_G) {
1949         x86_push_imm (s->code, tree->left->data.p);
1950 }
1951
1952 stmt: ARG_I4 (coni4) "MB_USE_OPT1(0)" {
1953         x86_push_imm (s->code, tree->left->data.i);
1954 }
1955
1956 this: reg {
1957         PRINT_REG ("THIS", tree->reg1);
1958 }
1959
1960 reg: CHECKTHIS (reg) {
1961         /* try to access the vtable - this will raise an exception
1962          * if the object is NULL */
1963         x86_alu_membase_imm (s->code, X86_CMP, tree->left->reg1, 0, 0);
1964         if (tree->reg1 != tree->left->reg1)
1965                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1966 }
1967
1968 stmt: CHECKTHIS (reg) {
1969         x86_alu_membase_imm (s->code, X86_CMP, tree->left->reg1, 0, 0);
1970 }
1971
1972 this: NOP
1973
1974 reg: CALL_I4 (this, reg) {
1975         int treg = X86_EAX;
1976         int lreg = tree->left->reg1;
1977         int rreg = tree->right->reg1;
1978         
1979         if (lreg == treg || rreg == treg) 
1980                 treg = X86_EDX;
1981         if (lreg == treg || rreg == treg) 
1982                 treg = X86_ECX;
1983         if (lreg == treg || rreg == treg) 
1984                 mono_assert_not_reached ();
1985
1986         if (tree->left->op != MB_TERM_NOP) {
1987                 mono_assert (lreg >= 0);
1988                 x86_push_reg (s->code, lreg);
1989         }
1990
1991         if (tree->data.ci.vtype_num) {
1992                 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.ci.vtype_num).offset;
1993                 x86_lea_membase (s->code, treg, X86_EBP, offset);
1994                 x86_push_reg (s->code, treg);
1995         }
1996
1997         x86_call_reg (s->code, rreg);
1998
1999         if (tree->data.ci.args_size)
2000                 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2001         
2002         PRINT_REG ("CALL_I4", tree->reg1);
2003
2004         mono_assert (tree->reg1 == X86_EAX);
2005 }
2006
2007 reg: CALL_I4 (this, ADDR_G) {
2008         int lreg = tree->left->reg1;
2009         int treg = X86_EAX;
2010
2011         if (lreg == treg) 
2012                 treg = X86_EDX;
2013         
2014         if (tree->left->op != MB_TERM_NOP) {
2015                 mono_assert (lreg >= 0);
2016                 x86_push_reg (s->code, lreg);
2017                 x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
2018         }
2019
2020         if (tree->data.ci.vtype_num) {
2021                 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.ci.vtype_num).offset;
2022                 x86_lea_membase (s->code, treg, X86_EBP, offset);
2023                 x86_push_reg (s->code, treg);
2024         }
2025
2026         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, tree->right->data.p);
2027         x86_call_code (s->code, 0);
2028
2029         if (tree->data.ci.args_size)
2030                 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2031
2032         PRINT_REG ("CALL_I4", tree->reg1);
2033
2034         mono_assert (tree->reg1 == X86_EAX);
2035 }
2036
2037 reg: LDVIRTFTN (reg, INTF_ADDR) {
2038         int lreg = tree->left->reg1;
2039
2040         x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2041         x86_mov_reg_membase (s->code, lreg, lreg, 
2042                 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
2043         x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
2044         x86_mov_reg_membase (s->code, tree->reg1, lreg, tree->right->data.m->slot << 2, 4);
2045 }
2046
2047 reg: CALL_I4 (this, INTF_ADDR) {
2048         int lreg = tree->left->reg1;
2049         int treg = X86_EAX;
2050
2051         if (lreg == treg) 
2052                 treg = X86_EDX;
2053
2054         if (tree->left->op != MB_TERM_NOP) {
2055                 mono_assert (lreg >= 0);
2056                 x86_push_reg (s->code, lreg);
2057         }
2058
2059         if (tree->data.ci.vtype_num) {
2060                 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.ci.vtype_num).offset;
2061                 x86_lea_membase (s->code, treg, X86_EBP, offset);
2062                 x86_push_reg (s->code, treg);
2063         }
2064
2065         x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2066         x86_mov_reg_membase (s->code, lreg, lreg, 
2067                 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
2068         x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
2069         x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
2070
2071         if (tree->data.ci.args_size)
2072                 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2073
2074         PRINT_REG ("CALL_I4(INTERFACE)", tree->reg1);
2075
2076         mono_assert (tree->reg1 == X86_EAX);
2077 }
2078
2079 reg: LDVIRTFTN (reg, VFUNC_ADDR) {
2080         int lreg = tree->left->reg1;
2081         
2082         x86_mov_reg_membase (s->code, tree->reg1, lreg, 0, 4);
2083         
2084         x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2), 4);
2085 }
2086
2087 reg: LDFTN {
2088         if (tree->reg1 != X86_EAX)
2089                 x86_push_reg (s->code, X86_EAX);
2090         x86_push_reg (s->code, X86_ECX);
2091         x86_push_reg (s->code, X86_EDX);
2092
2093         x86_push_imm (s->code, tree->data.m);
2094         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, arch_compile_method);
2095         x86_call_code (s->code, 0);
2096         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
2097
2098         x86_pop_reg (s->code, X86_EDX);
2099         x86_pop_reg (s->code, X86_ECX);
2100         if (tree->reg1 != X86_EAX) {
2101                 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
2102                 x86_pop_reg (s->code, X86_EAX);
2103         }
2104         PRINT_REG ("LDFTN", tree->reg1);
2105 }
2106
2107
2108 reg: CALL_I4 (this, VFUNC_ADDR) {
2109         int lreg = tree->left->reg1;
2110         int treg = X86_EAX;
2111
2112         if (lreg == treg) 
2113                 treg = X86_EDX;
2114
2115         if (tree->left->op != MB_TERM_NOP) {
2116                 mono_assert (lreg >= 0);
2117                 x86_push_reg (s->code, lreg);
2118         }
2119
2120         if (tree->data.ci.vtype_num) {
2121                 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.ci.vtype_num).offset;
2122                 x86_lea_membase (s->code, treg, X86_EBP, offset);
2123                 x86_push_reg (s->code, treg);
2124         }
2125
2126         x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);        
2127         x86_call_virtual (s->code, lreg, 
2128                 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
2129
2130         if (tree->data.ci.args_size)
2131                 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2132
2133         PRINT_REG ("CALL_I4(VIRTUAL)", tree->reg1);
2134
2135         mono_assert (tree->reg1 == X86_EAX);
2136 }
2137
2138 stmt: CALL_VOID (this, ADDR_G) {
2139         int lreg = tree->left->reg1;
2140         int treg = X86_EAX;
2141
2142         if (lreg == treg) 
2143                 treg = X86_EDX;
2144         
2145         if (tree->left->op != MB_TERM_NOP) {
2146                 mono_assert (lreg >= 0);
2147                 x86_push_reg (s->code, lreg);
2148                 x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
2149         }
2150
2151         if (tree->data.ci.vtype_num) {
2152                 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.ci.vtype_num).offset;
2153                 x86_lea_membase (s->code, treg, X86_EBP, offset);
2154                 x86_push_reg (s->code, treg);
2155         }
2156
2157         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, tree->right->data.p);
2158         x86_call_code (s->code, 0);
2159
2160         if (tree->data.ci.args_size)
2161                 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2162 }
2163
2164 stmt: CALL_VOID (this, INTF_ADDR) {
2165         int lreg = tree->left->reg1;
2166         int treg = X86_EAX;
2167
2168         if (lreg == treg) 
2169                 treg = X86_EDX;
2170
2171         if (tree->left->op != MB_TERM_NOP) {
2172                 mono_assert (lreg >= 0);
2173                 x86_push_reg (s->code, lreg);
2174         }
2175
2176         if (tree->data.ci.vtype_num) {
2177                 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.ci.vtype_num).offset;
2178                 x86_lea_membase (s->code, treg, X86_EBP, offset);
2179                 x86_push_reg (s->code, treg);
2180         }
2181
2182         x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2183         x86_mov_reg_membase (s->code, lreg, lreg, 
2184                 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
2185         x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
2186         x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
2187
2188         if (tree->data.ci.args_size)
2189                 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2190 }
2191
2192 stmt: CALL_VOID (this, VFUNC_ADDR) {
2193         int lreg = tree->left->reg1;
2194         int treg = X86_EAX;
2195
2196         if (lreg == treg) 
2197                 treg = X86_EDX;
2198
2199         if (tree->left->op != MB_TERM_NOP) {
2200                 mono_assert (lreg >= 0);
2201                 x86_push_reg (s->code, lreg);
2202         }
2203
2204         if (tree->data.ci.vtype_num) {
2205                 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.ci.vtype_num).offset;
2206                 x86_lea_membase (s->code, treg, X86_EBP, offset);
2207                 x86_push_reg (s->code, treg);
2208         }
2209
2210         x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2211         x86_call_virtual (s->code, lreg, 
2212                 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
2213
2214         if (tree->data.ci.args_size)
2215                 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2216 }
2217
2218 stmt: SWITCH (reg) {
2219         guint32 offset;
2220         guint32 *jt = (guint32 *)tree->data.p;
2221
2222         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, jt [0]);
2223         offset = 6 + (guint32)s->code;
2224         x86_branch32 (s->code, X86_CC_GE, jt [jt [0] + 1] - offset, FALSE);
2225
2226         x86_mov_reg_memindex (s->code, X86_EAX, X86_NOBASEREG, 
2227                               tree->data.i + 4, tree->left->reg1, 2, 4);        
2228         x86_jump_reg (s->code, X86_EAX);
2229 }
2230
2231 #
2232 # 64 bit integers
2233 #
2234
2235 reg: CONV_I1 (lreg) {
2236         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
2237
2238
2239 reg: CONV_I2 (lreg) {
2240         x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
2241
2242
2243 reg: CONV_I4 (lreg) {
2244         if (tree->reg1 != tree->left->reg1)
2245                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2246
2247
2248
2249 reg: CONV_OVF_I4 (lreg){
2250         guint8 *start = s->code;
2251         guchar* o1, *o2, *o3, *o4, *o5;
2252         int i;
2253
2254         /* 
2255          * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000
2256          */
2257         for (i = 0; i < 2; i++) {
2258                 s->code = start;
2259
2260                 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
2261
2262                 /* If the low word top bit is set, see if we are negative */
2263                 x86_branch8 (s->code, X86_CC_LT, o3 - o1, TRUE);
2264                 o1 = s->code;
2265
2266                 /* We are not negative (no top bit set, check for our top word to be zero */
2267                 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
2268                 x86_branch8 (s->code, X86_CC_EQ, o4 - o2, TRUE);
2269                 o2 = s->code;
2270
2271                 /* throw exception */
2272                 x86_push_imm (s->code, "OverflowException");
2273                 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, 
2274                                     arch_get_throw_exception_by_name ());
2275                 x86_call_code (s->code, 0);
2276         
2277                 o3 = s->code;
2278                 /* our top bit is set, check that top word is 0xfffffff */
2279                 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg2, 0xffffffff);
2280                 
2281                 o4 = s->code;
2282                 /* nope, emit exception */
2283                 x86_branch8 (s->code, X86_CC_NE, o2 - o5, TRUE);
2284                 o5 = s->code;
2285
2286                 if (tree->reg1 != tree->left->reg1)
2287                         x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2288         }
2289 }
2290 reg: CONV_OVF_I4 (lreg){
2291         guint8 *br [3], *label [1];
2292
2293         /* 
2294          * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000
2295          */
2296         x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
2297
2298         /* If the low word top bit is set, see if we are negative */
2299         br [0] = s->code; x86_branch8 (s->code, X86_CC_LT, 0, TRUE);
2300
2301         /* We are not negative (no top bit set, check for our top word to be zero */
2302         x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
2303         br [1] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, TRUE);
2304         label [0] = s->code;
2305
2306         /* throw exception */
2307         x86_push_imm (s->code, "OverflowException");
2308         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, 
2309                             arch_get_throw_exception_by_name ());
2310         x86_call_code (s->code, 0);
2311         
2312         x86_patch (br [0], s->code);
2313         /* our top bit is set, check that top word is 0xfffffff */
2314         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg2, 0xffffffff);
2315                 
2316         x86_patch (br [1], s->code);
2317         /* nope, emit exception */
2318         br [2] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
2319         x86_patch (br [2], label [0]);
2320
2321         if (tree->reg1 != tree->left->reg1)
2322                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2323 }
2324
2325 reg: CONV_OVF_U4 (lreg) {
2326         /* Keep in sync with CONV_OVF_I4_UN below, they are the same on 32-bit machines */
2327         /* top word must be 0 */
2328         x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
2329         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
2330         if (tree->reg1 != tree->left->reg1)
2331                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2332 }
2333
2334 reg: CONV_OVF_I4_UN (lreg) {
2335         /* Keep in sync with CONV_OVF_U4 above, they are the same on 32-bit machines */
2336         /* top word must be 0 */
2337         x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
2338         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
2339         if (tree->reg1 != tree->left->reg1)
2340                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2341 }
2342
2343 stmt: POP (lreg)
2344
2345 lreg: CONST_I8 1 {
2346         x86_mov_reg_imm (s->code, tree->reg1, *((gint32 *)&tree->data.p));
2347         x86_mov_reg_imm (s->code, tree->reg2, *((gint32 *)&tree->data.p + 1));
2348 }
2349
2350 lreg: CONV_I8 (coni4) {
2351         x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
2352
2353         if (tree->left->data.i >= 0)
2354                 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2355         else 
2356                 x86_mov_reg_imm (s->code, tree->reg2, -1);              
2357 }
2358
2359 lreg: CONV_I8 (reg) {
2360         guint8 *i1;
2361
2362         if (tree->reg1 != tree->left->reg1)
2363                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2364
2365         x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2366         x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
2367         x86_branch8 (s->code, X86_CC_GE, 5, TRUE);
2368         i1 = s->code;
2369         x86_mov_reg_imm (s->code, tree->reg2, -1); 
2370         mono_assert ((s->code - i1) == 5);
2371 }
2372
2373 lreg: CONV_U8 (coni4) 1 {
2374         x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
2375         x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2376 }
2377
2378 lreg: CONV_U8 (reg) {
2379         if (tree->reg1 != tree->left->reg1)
2380                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2381         x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2382 }
2383
2384 lreg: CONV_OVF_U8 (coni4) {
2385         if (tree->left->data.i < 0){
2386                 x86_push_imm (s->code, "OverflowException");
2387                 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, 
2388                                     arch_get_throw_exception_by_name ());
2389                 x86_call_code (s->code, 0);
2390         } else {
2391                 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
2392                 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2393         }
2394 }
2395
2396 lreg: CONV_OVF_I8_UN (coni4) {
2397         x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
2398         x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2399 }
2400
2401 lreg: CONV_OVF_U8 (reg) {
2402         x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
2403         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
2404
2405         if (tree->reg1 != tree->left->reg1)
2406                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2407         x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2408 }
2409
2410 lreg: CONV_OVF_I8_UN (reg) {
2411         /* Convert uint value into int64, we pass everything */
2412         if (tree->reg1 != tree->left->reg1)
2413                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2414         x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2415 }
2416
2417 stmt: STIND_I8 (addr, lreg) {
2418        
2419         switch (tree->left->data.ainfo.amode) {
2420
2421         case AMImmediate:
2422                 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
2423                 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset + 4, tree->right->reg2, 4);
2424                 break;
2425                 
2426         case AMBase:
2427                 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg, 
2428                                      tree->left->data.ainfo.offset, tree->right->reg1, 4);
2429                 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg, 
2430                                      tree->left->data.ainfo.offset + 4, tree->right->reg2, 4);
2431                 break;          
2432         case AMIndex:
2433                 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
2434                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2435                                       tree->right->reg1, 4);
2436                 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset + 4,
2437                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2438                                       tree->right->reg2, 4);
2439                 break;          
2440         case AMBaseIndex:
2441                 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
2442                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2443                                       tree->right->reg1, 4);
2444                 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset + 4,
2445                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2446                                       tree->right->reg2, 4);
2447                 break;          
2448         }
2449
2450 }
2451
2452 stmt: REMOTE_STIND_I8 (reg, lreg) {
2453         guint8 *br[2];
2454         int offset;
2455
2456         x86_push_reg (s->code, tree->right->reg1);
2457         x86_mov_reg_membase (s->code, tree->right->reg1, tree->left->reg1, 0, 4);
2458         x86_alu_membase_imm (s->code, X86_CMP, tree->right->reg1, 0, ((int)mono_defaults.transparent_proxy_class));
2459         x86_pop_reg (s->code, tree->right->reg1);
2460         
2461         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
2462
2463         /* this is a transparent proxy - remote the call */
2464
2465         /* save value to stack */
2466         x86_push_reg (s->code, tree->right->reg2);
2467         x86_push_reg (s->code, tree->right->reg1);
2468
2469         x86_push_reg (s->code, X86_ESP);
2470         x86_push_imm (s->code, tree->data.fi.field);
2471         x86_push_imm (s->code, tree->data.fi.klass);
2472         x86_push_reg (s->code, tree->left->reg1);
2473         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_store_remote_field);
2474         x86_call_code (s->code, 0);
2475         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 24);
2476
2477         br [1] = s->code; x86_jump8 (s->code, 0);
2478
2479         x86_patch (br [0], s->code);
2480         offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) : 
2481                 tree->data.fi.field->offset;
2482         x86_mov_membase_reg (s->code, tree->left->reg1, offset, tree->right->reg1, 4);
2483         x86_mov_membase_reg (s->code, tree->left->reg1, offset + 4, tree->right->reg2, 4);
2484
2485         x86_patch (br [1], s->code);
2486 }
2487
2488
2489 # an addr can use two address register (base and index register). The must take care 
2490 # that we do not override them (thus the use of x86_lea)
2491 lreg: LDIND_I8 (addr) {
2492
2493         switch (tree->left->data.ainfo.amode) {
2494
2495         case AMImmediate:
2496                 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
2497                 x86_mov_reg_mem (s->code, tree->reg2, tree->left->data.ainfo.offset + 4, 4);
2498                 break;
2499
2500         case AMBase:
2501                 x86_lea_membase (s->code, tree->reg2, tree->left->data.ainfo.basereg,
2502                                  tree->left->data.ainfo.offset);
2503                 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
2504                 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
2505                 break;          
2506         case AMIndex:
2507                 x86_lea_memindex (s->code, tree->reg2, X86_NOBASEREG, tree->left->data.ainfo.offset,
2508                                       tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift);
2509                 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
2510                 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
2511                 break;          
2512         case AMBaseIndex:
2513                 x86_lea_memindex (s->code, tree->reg2, tree->left->data.ainfo.basereg, 
2514                                   tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg, 
2515                                   tree->left->data.ainfo.shift);
2516                 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
2517                 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
2518                 break;          
2519         }
2520         PRINT_REG ("LDIND_I8_0", tree->reg1);
2521         PRINT_REG ("LDIND_I8_1", tree->reg2);
2522 }
2523
2524 lreg: SHR (lreg, coni4) {
2525         if (tree->right->data.i < 32) {
2526                 x86_shrd_reg_imm (s->code, tree->left->reg1, tree->left->reg2, tree->right->data.i);
2527                 x86_shift_reg_imm (s->code, X86_SAR, tree->left->reg2, tree->right->data.i);
2528                 if (tree->reg1 != tree->left->reg1)
2529                         x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2530                 if (tree->reg2 != tree->left->reg2)
2531                         x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2532         } else if (tree->right->data.i < 64) {
2533                 if (tree->reg1 != tree->left->reg2)
2534                         x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg2, 4);
2535                 if (tree->reg2 != tree->left->reg2)
2536                         x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2537                 x86_shift_reg_imm (s->code, X86_SAR, tree->reg2, 31);
2538                 x86_shift_reg_imm (s->code, X86_SAR, tree->reg1, (tree->right->data.i - 32));
2539         } /* else unspecified result */
2540 }
2541
2542 lreg: SHR_UN (lreg, coni4) {
2543         if (tree->right->data.i < 32) {
2544                 x86_shrd_reg_imm (s->code, tree->left->reg1, tree->left->reg2, tree->right->data.i);
2545                 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg2, tree->right->data.i);
2546                 if (tree->reg1 != tree->left->reg1)
2547                         x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2548                 if (tree->reg2 != tree->left->reg2)
2549                         x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2550         } else if (tree->right->data.i < 64) {
2551                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg2, 4);
2552                 x86_shift_reg_imm (s->code, X86_SHR, tree->reg1, (tree->right->data.i - 32));
2553                 x86_mov_reg_imm (s->code, tree->reg2, 0);
2554         } /* else unspecified result */
2555 }
2556
2557 lreg: SHR (lreg, reg) {
2558         guint8 *br [1];
2559
2560         if (tree->right->reg1 != X86_ECX)
2561                 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
2562
2563         x86_shrd_reg (s->code, tree->left->reg1, tree->left->reg2);
2564         x86_shift_reg (s->code, X86_SAR, tree->left->reg2);
2565         x86_test_reg_imm (s->code, X86_ECX, 32);
2566         br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
2567         x86_mov_reg_reg (s->code, tree->left->reg1, tree->left->reg2, 4);
2568         x86_shift_reg_imm (s->code, X86_SAR, tree->reg2, 31);           
2569         x86_patch (br [0], s->code);
2570
2571         if (tree->reg1 != tree->left->reg1)
2572                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2573         if (tree->reg2 != tree->left->reg2)
2574                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2575 }
2576
2577 lreg: SHR_UN (lreg, reg) {
2578         guint8 *br [1];
2579
2580         if (tree->right->reg1 != X86_ECX)
2581                 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
2582
2583         x86_shrd_reg (s->code, tree->left->reg1, tree->left->reg2);
2584         x86_shift_reg (s->code, X86_SHR, tree->left->reg2);
2585         x86_test_reg_imm (s->code, X86_ECX, 32);
2586         br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
2587         x86_mov_reg_reg (s->code, tree->left->reg1, tree->left->reg2, 4);
2588         x86_shift_reg_imm (s->code, X86_SHR, tree->reg2, 31);           
2589         x86_patch (br [0], s->code);
2590
2591         if (tree->reg1 != tree->left->reg1)
2592                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2593         if (tree->reg2 != tree->left->reg2)
2594                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2595 }
2596
2597 lreg: SHL (lreg, coni4) {
2598         if (tree->right->data.i < 32) {
2599                 x86_shld_reg_imm (s->code, tree->left->reg2, tree->left->reg1, tree->right->data.i);
2600                 x86_shift_reg_imm (s->code, X86_SHL, tree->left->reg1, tree->right->data.i);
2601                 if (tree->reg1 != tree->left->reg1)
2602                         x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2603                 if (tree->reg2 != tree->left->reg2)
2604                         x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2605         } else if (tree->right->data.i < 64) {
2606                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg1, 4);
2607                 x86_shift_reg_imm (s->code, X86_SHL, tree->reg2, (tree->right->data.i - 32));
2608                 x86_alu_reg_reg (s->code, X86_XOR, tree->reg1, tree->reg1);     
2609         } /* else unspecified result */
2610 }
2611
2612 lreg: SHL (lreg, reg) {
2613         guint8 *br [1];
2614
2615         if (tree->right->reg1 != X86_ECX)
2616                 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
2617
2618         x86_shld_reg (s->code, tree->left->reg2, tree->left->reg1);
2619         x86_shift_reg (s->code, X86_SHL, tree->left->reg1);
2620         x86_test_reg_imm (s->code, X86_ECX, 32);
2621         br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
2622         x86_mov_reg_reg (s->code, tree->left->reg2, tree->left->reg1, 4);
2623         x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->left->reg1); 
2624         x86_patch (br [0], s->code);
2625
2626         if (tree->reg1 != tree->left->reg1)
2627                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2628         if (tree->reg2 != tree->left->reg2)
2629                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2630 }
2631
2632 lreg: ADD (lreg, lreg) {
2633         x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
2634         x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
2635
2636         if (tree->reg1 != tree->left->reg1)
2637                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2638         if (tree->reg2 != tree->left->reg2)
2639                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2640 }
2641
2642 lreg: ADD_OVF (lreg, lreg) {
2643         x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
2644         x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
2645         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");      
2646
2647         if (tree->reg1 != tree->left->reg1)
2648                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2649         if (tree->reg2 != tree->left->reg2)
2650                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2651 }
2652
2653 lreg: ADD_OVF_UN (lreg, lreg) {
2654         x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
2655         x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
2656         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");     
2657
2658         if (tree->reg1 != tree->left->reg1)
2659                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2660         if (tree->reg2 != tree->left->reg2)
2661                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2662 }
2663
2664 lreg: SUB (lreg, lreg) {
2665         x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
2666         x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
2667
2668         if (tree->reg1 != tree->left->reg1)
2669                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2670         if (tree->reg2 != tree->left->reg2)
2671                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2672 }
2673
2674 lreg: SUB_OVF (lreg, lreg) {
2675         x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
2676         x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
2677         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");      
2678
2679         if (tree->reg1 != tree->left->reg1)
2680                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2681         if (tree->reg2 != tree->left->reg2)
2682                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2683 }
2684
2685 lreg: SUB_OVF_UN (lreg, lreg) {
2686         x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
2687         x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
2688         EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");     
2689
2690         if (tree->reg1 != tree->left->reg1)
2691                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2692         if (tree->reg2 != tree->left->reg2)
2693                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2694 }
2695
2696 lreg: AND (lreg, lreg) {
2697         x86_alu_reg_reg (s->code, X86_AND, tree->left->reg1, tree->right->reg1);
2698         x86_alu_reg_reg (s->code, X86_AND, tree->left->reg2, tree->right->reg2);
2699
2700         if (tree->reg1 != tree->left->reg1)
2701                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2702         if (tree->reg2 != tree->left->reg2)
2703                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2704 }
2705
2706 lreg: OR (lreg, lreg) {
2707         x86_alu_reg_reg (s->code, X86_OR, tree->left->reg1, tree->right->reg1);
2708         x86_alu_reg_reg (s->code, X86_OR, tree->left->reg2, tree->right->reg2);
2709
2710         if (tree->reg1 != tree->left->reg1)
2711                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2712         if (tree->reg2 != tree->left->reg2)
2713                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2714 }
2715
2716 lreg: XOR (lreg, lreg) {
2717         x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->right->reg1);
2718         x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg2, tree->right->reg2);
2719
2720         if (tree->reg1 != tree->left->reg1)
2721                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2722         if (tree->reg2 != tree->left->reg2)
2723                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2724 }
2725
2726 lreg: NEG (lreg) {
2727         if (tree->reg1 != tree->left->reg1)
2728                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2729         if (tree->reg2 != tree->left->reg2)
2730                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2731
2732         x86_neg_reg (s->code, tree->reg1);
2733         x86_alu_reg_imm (s->code, X86_ADC, tree->reg2, 0);
2734         x86_neg_reg (s->code, tree->reg2);
2735 }
2736
2737 lreg: NOT (lreg) {
2738         if (tree->reg1 != tree->left->reg1)
2739                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2740         if (tree->reg2 != tree->left->reg2)
2741                 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2742
2743          x86_not_reg (s->code, tree->reg1);
2744          x86_not_reg (s->code, tree->reg2);
2745 }
2746
2747 lreg: MUL (lreg, lreg) {
2748         if (mono_regset_reg_used (s->rs, X86_ECX)) 
2749                 x86_push_reg (s->code, X86_ECX);
2750
2751         x86_push_reg (s->code, tree->right->reg2);
2752         x86_push_reg (s->code, tree->right->reg1);
2753         x86_push_reg (s->code, tree->left->reg2);
2754         x86_push_reg (s->code, tree->left->reg1);
2755         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_llmult);
2756         x86_call_code (s->code, 0);
2757         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2758
2759         if (mono_regset_reg_used (s->rs, X86_ECX))
2760                 x86_pop_reg (s->code, X86_ECX);
2761
2762         mono_assert (tree->reg1 == X86_EAX &&
2763                   tree->reg2 == X86_EDX);
2764 }
2765
2766 lreg: MUL_OVF (lreg, lreg) {
2767         if (mono_regset_reg_used (s->rs, X86_ECX)) 
2768                 x86_push_reg (s->code, X86_ECX);
2769
2770         x86_push_reg (s->code, tree->right->reg2);
2771         x86_push_reg (s->code, tree->right->reg1);
2772         x86_push_reg (s->code, tree->left->reg2);
2773         x86_push_reg (s->code, tree->left->reg1);
2774         /* pass a pointer to store the resulting exception -
2775          * ugly, but it works */
2776         x86_push_reg (s->code, X86_ESP); 
2777         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_llmult_ovf);
2778         x86_call_code (s->code, 0);
2779         x86_mov_reg_membase (s->code, X86_ECX, X86_ESP, 4, 4);
2780         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
2781         x86_alu_reg_imm (s->code, X86_CMP, X86_ECX, 0);
2782
2783         /* cond. emit exception */
2784         x86_branch8 (s->code, X86_CC_EQ, 7, FALSE);                     
2785         x86_push_reg (s->code, X86_ECX);
2786         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, arch_get_throw_exception ());
2787         x86_call_code (s->code, 0);
2788
2789         if (mono_regset_reg_used (s->rs, X86_ECX))
2790                 x86_pop_reg (s->code, X86_ECX);
2791
2792         mono_assert (tree->reg1 == X86_EAX &&
2793                   tree->reg2 == X86_EDX);
2794 }
2795
2796 lreg: MUL_OVF_UN (lreg, lreg) {
2797         if (mono_regset_reg_used (s->rs, X86_ECX)) 
2798                 x86_push_reg (s->code, X86_ECX);
2799
2800         x86_push_reg (s->code, tree->right->reg2);
2801         x86_push_reg (s->code, tree->right->reg1);
2802         x86_push_reg (s->code, tree->left->reg2);
2803         x86_push_reg (s->code, tree->left->reg1);
2804         /* pass a pointer to store the resulting exception -
2805          * ugly, but it works */
2806         x86_push_reg (s->code, X86_ESP); 
2807         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_llmult_ovf_un);
2808         x86_call_code (s->code, 0);
2809         x86_mov_reg_membase (s->code, X86_ECX, X86_ESP, 4, 4);
2810         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
2811         x86_alu_reg_imm (s->code, X86_CMP, X86_ECX, 0);
2812
2813         /* cond. emit exception */
2814         x86_branch8 (s->code, X86_CC_EQ, 7, FALSE);                     
2815         x86_push_reg (s->code, X86_ECX);                                 
2816         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, arch_get_throw_exception ());
2817         x86_call_code (s->code, 0);
2818
2819         if (mono_regset_reg_used (s->rs, X86_ECX))
2820                 x86_pop_reg (s->code, X86_ECX);
2821
2822         mono_assert (tree->reg1 == X86_EAX &&
2823                   tree->reg2 == X86_EDX);
2824 }
2825
2826 lreg: DIV (lreg, lreg) {
2827         if (mono_regset_reg_used (s->rs, X86_ECX)) 
2828                 x86_push_reg (s->code, X86_ECX);
2829
2830         x86_push_reg (s->code, tree->right->reg2);
2831         x86_push_reg (s->code, tree->right->reg1);
2832         x86_push_reg (s->code, tree->left->reg2);
2833         x86_push_reg (s->code, tree->left->reg1);
2834         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_lldiv);
2835         x86_call_code (s->code, 0);
2836         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2837
2838         if (mono_regset_reg_used (s->rs, X86_ECX))
2839                 x86_pop_reg (s->code, X86_ECX);
2840
2841         mono_assert (tree->reg1 == X86_EAX &&
2842                   tree->reg2 == X86_EDX);
2843 }
2844
2845 lreg: REM (lreg, lreg) {
2846         if (mono_regset_reg_used (s->rs, X86_ECX)) 
2847                 x86_push_reg (s->code, X86_ECX);
2848
2849         x86_push_reg (s->code, tree->right->reg2);
2850         x86_push_reg (s->code, tree->right->reg1);
2851         x86_push_reg (s->code, tree->left->reg2);
2852         x86_push_reg (s->code, tree->left->reg1);
2853         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_llrem);
2854         x86_call_code (s->code, 0);
2855         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2856
2857         if (mono_regset_reg_used (s->rs, X86_ECX))
2858                 x86_pop_reg (s->code, X86_ECX);
2859
2860         mono_assert (tree->reg1 == X86_EAX &&
2861                   tree->reg2 == X86_EDX);
2862 }
2863
2864 lreg: DIV_UN (lreg, lreg) {
2865         if (mono_regset_reg_used (s->rs, X86_ECX)) 
2866                 x86_push_reg (s->code, X86_ECX);
2867
2868         x86_push_reg (s->code, tree->right->reg2);
2869         x86_push_reg (s->code, tree->right->reg1);
2870         x86_push_reg (s->code, tree->left->reg2);
2871         x86_push_reg (s->code, tree->left->reg1);
2872         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_lldiv_un);
2873         x86_call_code (s->code, 0);
2874         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2875
2876         if (mono_regset_reg_used (s->rs, X86_ECX))
2877                 x86_pop_reg (s->code, X86_ECX);
2878
2879         mono_assert (tree->reg1 == X86_EAX &&
2880                   tree->reg2 == X86_EDX);
2881 }
2882
2883 lreg: REM_UN (lreg, lreg) {
2884         if (mono_regset_reg_used (s->rs, X86_ECX)) 
2885                 x86_push_reg (s->code, X86_ECX);
2886
2887         x86_push_reg (s->code, tree->right->reg2);
2888         x86_push_reg (s->code, tree->right->reg1);
2889         x86_push_reg (s->code, tree->left->reg2);
2890         x86_push_reg (s->code, tree->left->reg1);
2891         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_llrem_un);
2892         x86_call_code (s->code, 0);
2893         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2894
2895         if (mono_regset_reg_used (s->rs, X86_ECX))
2896                 x86_pop_reg (s->code, X86_ECX);
2897
2898         mono_assert (tree->reg1 == X86_EAX &&
2899                   tree->reg2 == X86_EDX);
2900 }
2901
2902 lreg: CALL_I8 (this, ADDR_G) {
2903         int lreg = tree->left->reg1;
2904         int treg = X86_EAX;
2905
2906         if (lreg == treg) 
2907                 treg = X86_EDX;
2908         
2909         if (tree->left->op != MB_TERM_NOP) {
2910                 mono_assert (lreg >= 0);
2911                 x86_push_reg (s->code, lreg);
2912                 x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
2913         }
2914
2915         if (tree->data.ci.vtype_num) {
2916                 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.ci.vtype_num).offset;
2917                 x86_lea_membase (s->code, treg, X86_EBP, offset);
2918                 x86_push_reg (s->code, treg);
2919         }
2920
2921         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, tree->right->data.p);
2922         x86_call_code (s->code, 0);
2923
2924         if (tree->data.ci.args_size)
2925                 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2926
2927         mono_assert (tree->reg1 == X86_EAX);
2928         mono_assert (tree->reg2 == X86_EDX);
2929 }
2930
2931 lreg: CALL_I8 (this, VFUNC_ADDR) {
2932         int lreg = tree->left->reg1;
2933         int treg = X86_EAX;
2934
2935         if (lreg == treg) 
2936                 treg = X86_EDX;
2937
2938         if (tree->left->op != MB_TERM_NOP) {
2939                 mono_assert (lreg >= 0);
2940                 x86_push_reg (s->code, lreg);
2941         }
2942
2943         if (tree->data.ci.vtype_num) {
2944                 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.ci.vtype_num).offset;
2945                 x86_lea_membase (s->code, treg, X86_EBP, offset);
2946                 x86_push_reg (s->code, treg);
2947         }
2948
2949         x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2950         x86_call_virtual (s->code, lreg, 
2951                 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
2952
2953         if (tree->data.ci.args_size)
2954                 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2955
2956         PRINT_REG ("CALL0_I8(VIRTUAL)", tree->reg1);
2957         PRINT_REG ("CALL1_I8(VIRTUAL)", tree->reg2);
2958
2959         mono_assert (tree->reg1 == X86_EAX);
2960         mono_assert (tree->reg2 == X86_EDX);
2961 }
2962
2963 lreg: CALL_I8 (this, INTF_ADDR) {
2964         int lreg = tree->left->reg1;
2965         int treg = X86_EAX;
2966
2967         if (lreg == treg) 
2968                 treg = X86_EDX;
2969
2970         if (tree->left->op != MB_TERM_NOP) {
2971                 mono_assert (lreg >= 0);
2972                 x86_push_reg (s->code, lreg);
2973         }
2974
2975         if (tree->data.ci.vtype_num) {
2976                 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.ci.vtype_num).offset;
2977                 x86_lea_membase (s->code, treg, X86_EBP, offset);
2978                 x86_push_reg (s->code, treg);
2979         }
2980
2981         x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2982         x86_mov_reg_membase (s->code, lreg, lreg, 
2983                 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
2984         x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
2985         x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
2986
2987         if (tree->data.ci.args_size)
2988                 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2989
2990         PRINT_REG ("CALL_I8(INTERFACE)", tree->reg1);
2991
2992         mono_assert (tree->reg1 == X86_EAX);
2993         mono_assert (tree->reg2 == X86_EDX);
2994 }
2995
2996 stmt: RET (lreg) {
2997         if (tree->left->reg1 != X86_EAX) {
2998                 if (tree->left->reg2 != X86_EAX) {
2999                         x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
3000                         if (tree->left->reg2 != X86_EDX)
3001                                 x86_mov_reg_reg (s->code, X86_EDX, tree->left->reg2, 4);
3002                 } else { 
3003                         x86_mov_reg_reg (s->code, X86_ECX, tree->left->reg2, 4);
3004                         x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
3005                         x86_mov_reg_reg (s->code, X86_EDX, X86_ECX, 4);
3006                 }
3007         } else if (tree->left->reg2 != X86_EDX) {
3008                 x86_mov_reg_reg (s->code, X86_EDX, tree->left->reg2, 4);
3009         }
3010
3011         if (!tree->last_instr) {
3012                 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_EPILOG, NULL);
3013                 x86_jump32 (s->code, 0);      
3014         }
3015 }
3016
3017
3018 stmt: ARG_I8 (lreg) {
3019         x86_push_reg (s->code, tree->left->reg2);
3020         x86_push_reg (s->code, tree->left->reg1);
3021 }
3022
3023 reg: CEQ (lreg, lreg) {
3024         guint8 *br [1];
3025
3026         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
3027         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3028         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3029         x86_patch (br [0], s->code);
3030         x86_set_reg (s->code, X86_CC_EQ, tree->reg1, FALSE);
3031         x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
3032 }
3033
3034 reg: CLT (lreg, lreg) {
3035         guint8 *br [4];
3036
3037         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3038         br [0] = s->code; x86_branch8 (s->code, X86_CC_GT, 0, TRUE);
3039         br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3040         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
3041         br [2] = s->code; x86_branch8 (s->code, X86_CC_GE, 0, FALSE);
3042
3043         /* set result to 1 */
3044         x86_patch (br [1], s->code);
3045         x86_mov_reg_imm (s->code, tree->reg1, 1);
3046         br [3] = s->code; x86_jump8 (s->code, 0);
3047
3048         /* set result to 0 */
3049         x86_patch (br [0], s->code);
3050         x86_patch (br [2], s->code);
3051         x86_mov_reg_imm (s->code, tree->reg1, 0);       
3052
3053         x86_patch (br [3], s->code);
3054 }
3055
3056 reg: CLT_UN (lreg, lreg) {
3057         guint8 *br [4];
3058
3059         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3060         br [0] = s->code; x86_branch8 (s->code, X86_CC_GT, 0, FALSE);
3061         br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3062         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
3063         br [2] = s->code; x86_branch8 (s->code, X86_CC_GE, 0, FALSE);
3064
3065         /* set result to 1 */
3066         x86_patch (br [1], s->code);
3067         x86_mov_reg_imm (s->code, tree->reg1, 1);
3068         br [3] = s->code; x86_jump8 (s->code, 0);
3069         
3070         /* set result to 0 */
3071         x86_patch (br [0], s->code);
3072         x86_patch (br [2], s->code);
3073         x86_mov_reg_imm (s->code, tree->reg1, 0);       
3074
3075         x86_patch (br [3], s->code);    
3076 }
3077
3078 reg: CGT (lreg, lreg) {
3079         guint8 *br [4];
3080
3081         x86_alu_reg_reg (s->code, X86_CMP, tree->right->reg2, tree->left->reg2);
3082         br [0] = s->code; x86_branch8 (s->code, X86_CC_GT, 0, TRUE);
3083         br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3084         x86_alu_reg_reg (s->code, X86_CMP, tree->right->reg1, tree->left->reg1);
3085         br [2] = s->code; x86_branch8 (s->code, X86_CC_GE, 0, FALSE);
3086
3087         /* set result to 1 */
3088         x86_patch (br [1], s->code);
3089         x86_mov_reg_imm (s->code, tree->reg1, 1);
3090         br [3] = s->code; x86_jump8 (s->code, 0);
3091         
3092         /* set result to 0 */
3093         x86_patch (br [0], s->code);
3094         x86_patch (br [2], s->code);
3095         x86_mov_reg_imm (s->code, tree->reg1, 0);       
3096
3097         x86_patch (br [3], s->code);    
3098 }
3099
3100 reg: CGT_UN (lreg, lreg) {
3101         guint8 *br [4];
3102
3103         x86_alu_reg_reg (s->code, X86_CMP, tree->right->reg2, tree->left->reg2);
3104         br [0] = s->code; x86_branch8 (s->code, X86_CC_GT, 0, FALSE);
3105         br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3106         x86_alu_reg_reg (s->code, X86_CMP, tree->right->reg1, tree->left->reg1);
3107         br [2] = s->code; x86_branch8 (s->code, X86_CC_GE, 0, FALSE);
3108
3109         /* set result to 1 */
3110         x86_patch (br [1], s->code);
3111         x86_mov_reg_imm (s->code, tree->reg1, 1);
3112         br [3] = s->code; x86_jump8 (s->code, 0);
3113         
3114         /* set result to 0 */
3115         x86_patch (br [0], s->code);
3116         x86_patch (br [2], s->code);
3117         x86_mov_reg_imm (s->code, tree->reg1, 0);       
3118         
3119         x86_patch (br [3], s->code);    
3120 }
3121
3122 stmt: BEQ (lreg, lreg) {
3123         guint8 *br [1];
3124
3125         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
3126         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3127         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3128         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3129         x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
3130         x86_patch (br [0], s->code);
3131         
3132 }
3133
3134 stmt: BNE_UN (lreg, lreg) {
3135         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
3136         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3137         x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3138         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3139         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3140         x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3141 }
3142
3143 stmt: BGE (lreg, lreg) {
3144         guint8 *br [1];
3145
3146         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3147         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3148         x86_branch32 (s->code, X86_CC_GT, 0, TRUE);
3149         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3150         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3151         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
3152         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3153         x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
3154         x86_patch (br [0], s->code);
3155 }
3156
3157 stmt: BGE_UN (lreg, lreg) {
3158         guint8 *br [1];
3159
3160         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3161         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3162         x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
3163         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3164         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3165         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
3166         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3167         x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
3168         x86_patch (br [0], s->code);    
3169 }
3170
3171 stmt: BGT (lreg, lreg) {
3172         guint8 *br [1];
3173
3174         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3175         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3176         x86_branch32 (s->code, X86_CC_GT, 0, TRUE);
3177         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3178         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3179         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
3180         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3181         x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
3182         x86_patch (br [0], s->code);    
3183 }
3184
3185 stmt: BGT_UN (lreg, lreg) {
3186         guint8 *br [1];
3187
3188         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3189         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3190         x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
3191         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3192         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3193         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
3194         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3195         x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
3196         x86_patch (br [0], s->code);    
3197 }
3198
3199 stmt: BLT (lreg, lreg) {
3200         guint8 *br [1];
3201
3202         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3203         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3204         x86_branch32 (s->code, X86_CC_LT, 0, TRUE);
3205         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3206         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3207         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
3208         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3209         x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
3210         x86_patch (br [0], s->code);    
3211 }
3212
3213 stmt: BLT_UN (lreg, lreg) {
3214         guint8 *br [1];
3215
3216         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3217         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3218         x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
3219         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3220         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3221         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
3222         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3223         x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
3224         x86_patch (br [0], s->code);    
3225 }
3226
3227 stmt: BLE (lreg, lreg) {
3228         guint8 *br [1];
3229
3230         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3231         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3232         x86_branch32 (s->code, X86_CC_LT, 0, TRUE);
3233         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3234         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3235         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
3236         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3237         x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
3238         x86_patch (br [0], s->code);    
3239 }
3240
3241 stmt: BLE_UN (lreg, lreg) {
3242         guint8 *br [1];
3243
3244         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3245         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3246         x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
3247         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
3248         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3249         x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
3250         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3251         x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
3252         x86_patch (br [0], s->code);    
3253 }
3254
3255 #
3256 # floating point 
3257
3258 #stmt: STLOC (CONV_I4 (freg)) {
3259 #       // fixme: set CW
3260 #       x86_fist_pop_membase (s->code, X86_EBP, tree->data.i, FALSE);
3261 #} 
3262
3263 reg: CONV_I1 (freg) {
3264         x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3265         x86_fnstcw_membase(s->code, X86_ESP, 0);
3266         x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3267         x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3268         x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3269         x86_fldcw_membase (s->code, X86_ESP, 2);
3270         x86_push_reg (s->code, X86_EAX); // SP = SP - 4
3271         x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
3272         x86_pop_reg (s->code, tree->reg1);
3273         x86_widen_reg (s->code, tree->reg1, tree->reg1, TRUE, FALSE);
3274         x86_fldcw_membase (s->code, X86_ESP, 0);
3275         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3276 }
3277
3278 reg: CONV_I2 (freg) {
3279         x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3280         x86_fnstcw_membase(s->code, X86_ESP, 0);
3281         x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3282         x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3283         x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3284         x86_fldcw_membase (s->code, X86_ESP, 2);
3285         x86_push_reg (s->code, X86_EAX); // SP = SP - 4
3286         x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
3287         x86_pop_reg (s->code, tree->reg1);
3288         x86_widen_reg (s->code, tree->reg1, tree->reg1, TRUE, TRUE);
3289         x86_fldcw_membase (s->code, X86_ESP, 0);
3290         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3291 }
3292
3293 reg: CONV_I4 (freg) {
3294         x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3295         x86_fnstcw_membase(s->code, X86_ESP, 0);
3296         x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3297         x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3298         x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3299         x86_fldcw_membase (s->code, X86_ESP, 2);
3300         x86_push_reg (s->code, X86_EAX); // SP = SP - 4
3301         x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
3302         x86_pop_reg (s->code, tree->reg1);
3303         x86_fldcw_membase (s->code, X86_ESP, 0);
3304         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3305 }
3306
3307 lreg: CONV_I8 (freg) {
3308         x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3309         x86_fnstcw_membase(s->code, X86_ESP, 0);
3310         x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3311         x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3312         x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3313         x86_fldcw_membase (s->code, X86_ESP, 2);
3314         x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
3315         x86_fist_pop_membase (s->code, X86_ESP, 0, TRUE);
3316         x86_pop_reg (s->code, tree->reg1);
3317         x86_pop_reg (s->code, tree->reg2);
3318         x86_fldcw_membase (s->code, X86_ESP, 0);
3319         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3320 }
3321
3322 reg: CEQ (freg, freg) {
3323         int treg = tree->reg1;
3324         
3325         if (treg != X86_EAX)
3326                 x86_push_reg (s->code, X86_EAX); // save EAX
3327                 
3328         x86_fcompp (s->code);
3329         x86_fnstsw (s->code);
3330         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3331         x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
3332         x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
3333         x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
3334
3335         if (treg != X86_EAX)
3336                 x86_pop_reg (s->code, X86_EAX); // save EAX
3337 }
3338
3339 reg: CGT (freg, freg) {
3340         int treg = tree->reg1;
3341         
3342         if (treg != X86_EAX)
3343                 x86_push_reg (s->code, X86_EAX); // save EAX
3344                 
3345         x86_fcompp (s->code);
3346         x86_fnstsw (s->code);
3347         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3348         x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3349         x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
3350         x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
3351
3352         if (treg != X86_EAX)
3353                 x86_pop_reg (s->code, X86_EAX); // save EAX
3354 }
3355
3356 reg: CGT_UN (freg, freg) {
3357         int treg = tree->reg1;
3358         
3359         if (treg != X86_EAX)
3360                 x86_push_reg (s->code, X86_EAX); // save EAX
3361                 
3362         x86_fcompp (s->code);
3363         x86_fnstsw (s->code);
3364         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3365         x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3366         x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
3367         x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
3368
3369         if (treg != X86_EAX)
3370                 x86_pop_reg (s->code, X86_EAX); // save EAX
3371 }
3372
3373 reg: CLT (freg, freg) {
3374         int treg = tree->reg1;
3375         
3376         if (treg != X86_EAX)
3377                 x86_push_reg (s->code, X86_EAX); // save EAX
3378                 
3379         x86_fcompp (s->code);
3380         x86_fnstsw (s->code);
3381         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3382         x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
3383         x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
3384
3385         if (treg != X86_EAX)
3386                 x86_pop_reg (s->code, X86_EAX); // save EAX
3387 }
3388
3389 reg: CLT_UN (freg, freg) {
3390         int treg = tree->reg1;
3391         
3392         if (treg != X86_EAX)
3393                 x86_push_reg (s->code, X86_EAX); // save EAX
3394                 
3395         x86_fcompp (s->code);
3396         x86_fnstsw (s->code);
3397         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3398         x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
3399         x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
3400
3401         if (treg != X86_EAX)
3402                 x86_pop_reg (s->code, X86_EAX); // save EAX
3403 }
3404
3405 freg: CONV_R8 (freg) {
3406         /* nothing to do */
3407 }
3408
3409 freg: CONV_R4 (freg) {
3410         /* fixme: nothing to do ??*/
3411 }
3412
3413 freg: CONV_R8 (LDIND_I4 (ADDR_G)) {
3414         x86_fild (s->code, tree->left->left->data.p, FALSE);
3415 }
3416
3417 freg: CONV_R4 (reg) {
3418         x86_push_reg (s->code, tree->left->reg1);
3419         x86_fild_membase (s->code, X86_ESP, 0, FALSE);
3420         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3421 }
3422
3423 freg: CONV_R8 (reg) {
3424         x86_push_reg (s->code, tree->left->reg1);
3425         x86_fild_membase (s->code, X86_ESP, 0, FALSE);
3426         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3427 }
3428
3429 freg: CONV_R_UN (reg) {
3430         x86_push_imm (s->code, 0);
3431         x86_push_reg (s->code, tree->left->reg1);
3432         x86_fild_membase (s->code, X86_ESP, 0, TRUE);
3433         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
3434 }
3435
3436 freg: CONV_R_UN (lreg) {
3437         static guint8 mn[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x40 };
3438         guint8 *br [1];
3439
3440         /* load 64bit integer to FP stack */
3441         x86_push_imm (s->code, 0);
3442         x86_push_reg (s->code, tree->left->reg2);
3443         x86_push_reg (s->code, tree->left->reg1);
3444         x86_fild_membase (s->code, X86_ESP, 0, TRUE);
3445         /* store as 80bit FP value */
3446         x86_fst80_membase (s->code, X86_ESP, 0);
3447
3448         /* test if lreg is negative */
3449         x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
3450         br [0] = s->code; x86_branch8 (s->code, X86_CC_GEZ, 0, TRUE);
3451
3452         /* add correction constant mn */
3453         x86_fld80_mem (s->code, mn);
3454         x86_fld80_membase (s->code, X86_ESP, 0);
3455         x86_fp_op_reg (s->code, X86_FADD, 1, TRUE);
3456         x86_fst80_membase (s->code, X86_ESP, 0);
3457
3458         x86_patch (br [0], s->code);
3459
3460         x86_fld80_membase (s->code, X86_ESP, 0);
3461         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
3462 }
3463
3464 freg: CONV_R4 (lreg) {
3465         x86_push_reg (s->code, tree->left->reg2);
3466         x86_push_reg (s->code, tree->left->reg1);
3467         x86_fild_membase (s->code, X86_ESP, 0, TRUE);
3468         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
3469 }
3470
3471 freg: CONV_R8 (lreg) {
3472         x86_push_reg (s->code, tree->left->reg2);
3473         x86_push_reg (s->code, tree->left->reg1);
3474         x86_fild_membase (s->code, X86_ESP, 0, TRUE);
3475         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
3476 }
3477
3478 freg: CONST_R4 {
3479         float f = *(float *)tree->data.p;
3480
3481         if (f == 0.0)
3482                 x86_fldz (s->code);
3483         else if (f == 1.0)
3484                 x86_fld1(s->code);
3485         else
3486                 x86_fld (s->code, tree->data.p, FALSE);
3487 }
3488
3489 freg: CONST_R8 {
3490         double d = *(double *)tree->data.p;
3491
3492         if (d == 0.0)
3493                 x86_fldz (s->code);
3494         else if (d == 1.0)
3495                 x86_fld1(s->code);
3496         else
3497                 x86_fld (s->code, tree->data.p, TRUE);
3498 }
3499
3500 freg: LDIND_R4 (reg) {
3501         x86_fld_membase (s->code, tree->left->reg1, 0, FALSE);
3502 }
3503
3504 freg: LDIND_R8 (reg) {
3505         x86_fld_membase (s->code, tree->left->reg1, 0, TRUE);
3506 }
3507
3508 freg: ADD (freg, freg) {
3509         x86_fp_op_reg (s->code, X86_FADD, 1, TRUE);
3510 }
3511
3512 freg: SUB (freg, freg) {
3513         x86_fp_op_reg (s->code, X86_FSUB, 1, TRUE);
3514 }
3515
3516 freg: MUL (freg, freg) {
3517         x86_fp_op_reg (s->code, X86_FMUL, 1, TRUE);
3518 }
3519
3520 freg: DIV (freg, freg) {
3521         x86_fp_op_reg (s->code, X86_FDIV, 1, TRUE);
3522 }
3523
3524 freg: REM (freg, freg) {
3525         guint8 *l1, *l2;
3526
3527         /* we need to exchange ST(0) with ST(1) */
3528         x86_fxch (s->code, 1);
3529
3530         /* this requires a loop, because fprem1 somtimes 
3531          * returns a partial remainder */
3532         l1 = s->code;
3533         x86_fprem1 (s->code);
3534         x86_fnstsw (s->code);
3535         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x0400);
3536         l2 = s->code + 2;
3537         x86_branch8 (s->code, X86_CC_NE, l1 - l2, FALSE);
3538
3539         /* pop result */
3540         x86_fstp (s->code, 1);
3541 }
3542
3543 freg: NEG (freg) {
3544         x86_fchs (s->code);
3545 }
3546
3547 stmt: POP (freg)
3548
3549 stmt: STIND_R4 (ADDR_L, freg) {
3550         int offset = g_array_index (s->varinfo, MonoVarInfo, tree->left->data.i).offset;  
3551         x86_fst_membase (s->code, X86_EBP, offset, FALSE, TRUE);
3552 }
3553
3554 stmt: STIND_R4 (reg, freg) {
3555         x86_fst_membase (s->code, tree->left->reg1, 0, FALSE, TRUE);
3556 }
3557
3558 stmt: REMOTE_STIND_R4 (reg, freg) {
3559         guint8 *br[2];
3560         int treg = X86_EAX;
3561         int lreg = tree->left->reg1;
3562         int offset;
3563
3564         if (lreg == treg)
3565                 treg = X86_EDX;
3566
3567         x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
3568         x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
3569         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE); 
3570
3571         /* this is a transparent proxy - remote the call */
3572
3573         /* save value to stack */
3574         x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3575         x86_fst_membase (s->code, X86_ESP, 0, FALSE, TRUE);
3576
3577         x86_push_reg (s->code, X86_ESP);
3578         x86_push_imm (s->code, tree->data.fi.field);
3579         x86_push_imm (s->code, tree->data.fi.klass);
3580         x86_push_reg (s->code, lreg);
3581         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_store_remote_field);
3582         x86_call_code (s->code, 0);
3583         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
3584
3585         br [1] = s->code; x86_jump8 (s->code, 0); 
3586
3587         x86_patch (br [0], s->code);
3588         offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) : 
3589                 tree->data.fi.field->offset;
3590         x86_fst_membase (s->code, lreg, offset, FALSE, TRUE);
3591
3592         x86_patch (br [1], s->code);
3593 }
3594
3595 stmt: STIND_R8 (ADDR_L, freg) {
3596         int offset = g_array_index (s->varinfo, MonoVarInfo, tree->left->data.i).offset;  
3597         x86_fst_membase (s->code, X86_EBP, offset, TRUE, TRUE);
3598 }
3599
3600 stmt: STIND_R8 (reg, freg) {
3601         x86_fst_membase (s->code, tree->left->reg1, 0, TRUE, TRUE);
3602 }
3603
3604 stmt: REMOTE_STIND_R8 (reg, freg) {
3605         guint8 *br[2];
3606         int treg = X86_EAX;
3607         int lreg = tree->left->reg1;
3608         int offset;
3609
3610         if (lreg == treg)
3611                 treg = X86_EDX;
3612
3613         x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
3614         x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
3615         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE); 
3616
3617         /* this is a transparent proxy - remote the call */
3618
3619         /* save value to stack */
3620         x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
3621         x86_fst_membase (s->code, X86_ESP, 0, TRUE, TRUE);
3622
3623         x86_push_reg (s->code, X86_ESP);
3624         x86_push_imm (s->code, tree->data.fi.field);
3625         x86_push_imm (s->code, tree->data.fi.klass);
3626         x86_push_reg (s->code, lreg);
3627         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_store_remote_field);
3628         x86_call_code (s->code, 0);
3629         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 24);
3630
3631         br [1] = s->code; x86_jump8 (s->code, 0);
3632
3633         x86_patch (br [0], s->code);
3634         offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) : 
3635                 tree->data.fi.field->offset;
3636         x86_fst_membase (s->code, lreg, offset, TRUE, TRUE);
3637
3638         x86_patch (br [1], s->code);
3639 }
3640
3641 stmt: ARG_R4 (freg) {
3642         x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3643         x86_fst_membase (s->code, X86_ESP, 0, FALSE, TRUE);
3644 }
3645
3646 stmt: ARG_R8 (freg) {
3647         x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
3648         x86_fst_membase (s->code, X86_ESP, 0, TRUE, TRUE);
3649 }
3650
3651 # fixme: we need to implement unordered and ordered compares
3652
3653 stmt: BEQ (freg, freg) {
3654         x86_fcompp (s->code);
3655         x86_fnstsw (s->code);
3656         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3657         x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
3658         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3659         x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
3660 }
3661
3662 stmt: BNE_UN (freg, freg) {
3663         x86_fcompp (s->code);
3664         x86_fnstsw (s->code);
3665         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3666         x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
3667         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3668         x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3669 }
3670
3671 stmt: BLT (freg, freg) {
3672         x86_fcompp (s->code);
3673         x86_fnstsw (s->code);
3674         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3675         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3676         x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
3677 }
3678
3679 # fixme: unordered ??
3680 stmt: BLT_UN (freg, freg) {
3681         x86_fcompp (s->code);
3682         x86_fnstsw (s->code);
3683         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3684         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3685         x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
3686 }
3687
3688 stmt: BGE (freg, freg) {
3689         x86_fcompp (s->code);
3690         x86_fnstsw (s->code);
3691         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3692         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3693         x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3694 }
3695
3696 stmt: BGE_UN (freg, freg) {
3697         x86_fcompp (s->code);
3698         x86_fnstsw (s->code);
3699         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3700         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3701         x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3702 }
3703
3704 stmt: BGT (freg, freg) {
3705         x86_fcompp (s->code);
3706         x86_fnstsw (s->code);
3707         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3708         x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3709         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3710         x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
3711 }
3712
3713 stmt: BGT_UN (freg, freg) {
3714         x86_fcompp (s->code);
3715         x86_fnstsw (s->code);
3716         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3717         x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3718         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3719         x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
3720 }
3721
3722 stmt: BLE (freg, freg) {
3723         x86_fcompp (s->code);
3724         x86_fnstsw (s->code);
3725         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3726         x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3727         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3728         x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3729 }
3730
3731 stmt: BLE_UN (freg, freg) {
3732         x86_fcompp (s->code);
3733         x86_fnstsw (s->code);
3734         x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3735         x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3736         mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3737         x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3738 }
3739
3740 freg: CALL_R8 (this, ADDR_G) {
3741         int lreg = tree->left->reg1;
3742         int treg = X86_EAX;
3743
3744         if (lreg == treg) 
3745                 treg = X86_EDX;
3746         
3747         if (tree->left->op != MB_TERM_NOP) {
3748                 mono_assert (lreg >= 0);
3749                 x86_push_reg (s->code, lreg);
3750                 x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
3751         }
3752
3753         if (tree->data.ci.vtype_num) {
3754                 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.ci.vtype_num).offset;
3755                 x86_lea_membase (s->code, treg, X86_EBP, offset);
3756                 x86_push_reg (s->code, treg);
3757         }
3758
3759         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, tree->right->data.p);
3760         x86_call_code (s->code, 0);
3761
3762         if (tree->data.ci.args_size)
3763                 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
3764 }
3765
3766 freg: CALL_R8 (this, INTF_ADDR) {
3767         int lreg = tree->left->reg1;
3768         int treg = X86_EAX;
3769
3770         if (lreg == treg) 
3771                 treg = X86_EDX;
3772
3773         if (tree->left->op != MB_TERM_NOP) {
3774                 mono_assert (lreg >= 0);
3775                 x86_push_reg (s->code, lreg);
3776         }
3777
3778         if (tree->data.ci.vtype_num) {
3779                 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.ci.vtype_num).offset;
3780                 x86_lea_membase (s->code, treg, X86_EBP, offset);
3781                 x86_push_reg (s->code, treg);
3782         }
3783
3784         x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
3785         x86_mov_reg_membase (s->code, lreg, lreg, 
3786                 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
3787         x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
3788         x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
3789
3790         if (tree->data.ci.args_size)
3791                 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
3792 }
3793
3794 freg: CALL_R8 (this, VFUNC_ADDR) {
3795         int lreg = tree->left->reg1;
3796         int treg = X86_EAX;
3797
3798         if (lreg == treg) 
3799                 treg = X86_EDX;
3800
3801         if (tree->left->op != MB_TERM_NOP) {
3802                 mono_assert (lreg >= 0);
3803                 x86_push_reg (s->code, lreg);
3804         }
3805
3806         if (tree->data.ci.vtype_num) {
3807                 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.ci.vtype_num).offset;
3808                 x86_lea_membase (s->code, treg, X86_EBP, offset);
3809                 x86_push_reg (s->code, treg);
3810         }
3811
3812         x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
3813         x86_call_virtual (s->code, lreg, 
3814                 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
3815
3816         if (tree->data.ci.args_size)
3817                 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
3818 }
3819
3820 stmt: RET (freg) {
3821         if (!tree->last_instr) {
3822                 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_EPILOG, NULL);
3823                 x86_jump32 (s->code, 0);      
3824         }
3825 }
3826
3827 # support for value types
3828
3829 reg: LDIND_OBJ (reg) {
3830         if (tree->left->reg1 != tree->reg1)
3831                 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3832 }
3833
3834 stmt: STIND_OBJ (reg, reg) {
3835         mono_assert (tree->data.i > 0);
3836         x86_push_imm (s->code, tree->data.i);
3837         x86_push_reg (s->code, tree->right->reg1);
3838         x86_push_reg (s->code, tree->left->reg1);
3839         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, MEMCOPY);
3840         x86_call_code (s->code, 0);
3841         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
3842 }
3843
3844 stmt: REMOTE_STIND_OBJ (reg, reg) {
3845         guint8 *br[2];
3846         int treg = X86_EAX;
3847         int lreg = tree->left->reg1;
3848         int rreg = tree->right->reg1;
3849         int offset;
3850
3851         if (lreg == treg)
3852                 treg = X86_EDX;
3853
3854         if (rreg == treg)
3855                 treg = X86_ECX;
3856
3857         x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
3858         x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
3859         br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3860
3861         /* this is a transparent proxy - remote the call */
3862
3863         x86_push_reg (s->code, rreg);
3864         x86_push_imm (s->code, tree->data.fi.field);
3865         x86_push_imm (s->code, tree->data.fi.klass);
3866         x86_push_reg (s->code, lreg);
3867         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_store_remote_field);
3868         x86_call_code (s->code, 0);
3869         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
3870
3871         br [1] = s->code; x86_jump8 (s->code, 0);
3872
3873         x86_patch (br [0], s->code);
3874         offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) : 
3875                 tree->data.fi.field->offset;
3876
3877         x86_push_imm (s->code, mono_class_value_size (tree->data.fi.klass, NULL));
3878         x86_push_reg (s->code, tree->right->reg1);
3879         x86_alu_reg_imm (s->code, X86_ADD, tree->left->reg1, sizeof (MonoObject));      
3880         x86_push_reg (s->code, tree->left->reg1);
3881         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, MEMCOPY);
3882         x86_call_code (s->code, 0);
3883         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
3884
3885         x86_patch (br [1], s->code);
3886
3887         /* please test this first */
3888         g_assert_not_reached ();
3889 }
3890
3891 stmt: ARG_OBJ (coni4) {
3892         x86_push_imm (s->code, tree->left->data.i);     
3893 }
3894
3895 stmt: ARG_OBJ (reg) {
3896         int size = tree->data.i;
3897         int sa;
3898         
3899         mono_assert (size > 0);
3900
3901         sa = size + 3;
3902         sa &= ~3;
3903
3904         /* reserve space for the argument */
3905         x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);
3906
3907         x86_push_reg (s->code, X86_EAX);
3908         x86_push_reg (s->code, X86_EDX);
3909         x86_push_reg (s->code, X86_ECX);
3910
3911         x86_push_imm (s->code, size);
3912         x86_push_reg (s->code, tree->left->reg1);
3913         x86_lea_membase (s->code, X86_EAX, X86_ESP, 5*4);
3914         x86_push_reg (s->code, X86_EAX);
3915
3916         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, MEMCOPY);
3917         x86_call_code (s->code, 0);
3918         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
3919
3920         x86_pop_reg (s->code, X86_ECX);
3921         x86_pop_reg (s->code, X86_EDX);
3922         x86_pop_reg (s->code, X86_EAX);
3923 }
3924
3925 stmt: RET_OBJ (reg) {
3926         int size = tree->data.i;
3927
3928         x86_push_imm (s->code, size);
3929         x86_push_reg (s->code, tree->left->reg1);
3930         x86_push_membase (s->code, X86_EBP, 8);
3931
3932
3933         mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, MEMCOPY);
3934         x86_call_code (s->code, 0);
3935
3936         x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
3937
3938         if (!tree->last_instr) {
3939                 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_EPILOG, NULL);
3940                 x86_jump32 (s->code, 0);      
3941         }
3942 }
3943
3944 %% 
3945
3946 #include "jit.h"
3947
3948 gint64 
3949 mono_llmult (gint64 a, gint64 b)
3950 {
3951         return a * b;
3952 }
3953
3954 guint64  
3955 mono_llmult_ovf_un (gpointer *exc, guint32 al, guint32 ah, guint32 bl, guint32 bh)
3956 {
3957         guint64 res, t1;
3958
3959         // fixme: this is incredible slow
3960
3961         if (ah && bh)
3962                 goto raise_exception;
3963
3964         res = (guint64)al * (guint64)bl;
3965
3966         t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
3967
3968         if (t1 > 0xffffffff)
3969                 goto raise_exception;
3970
3971         res += ((guint64)t1) << 32; 
3972
3973         *exc = NULL;
3974         return res;
3975
3976  raise_exception:
3977         *exc = mono_get_exception_overflow ();
3978         return 0;
3979 }
3980
3981 guint64  
3982 mono_llmult_ovf (gpointer *exc, guint32 al, gint32 ah, guint32 bl, gint32 bh)
3983 {
3984         gint64 res, t1;
3985
3986         // fixme: check for overflow
3987
3988         res = (gint64)al * (gint64)bl;
3989
3990         t1 = (gint64)ah * bl + al * (gint64)bh;
3991
3992         res += ((gint64)t1) << 32; 
3993
3994         *exc = NULL;
3995         return res;
3996 /*
3997  raise_exception:
3998         *exc = mono_get_exception_overflow ();
3999         return 0;
4000 */
4001 }
4002
4003 gint64 
4004 mono_lldiv (gint64 a, gint64 b)
4005 {
4006         return a / b;
4007 }
4008
4009 gint64 
4010 mono_llrem (gint64 a, gint64 b)
4011 {
4012         return a % b;
4013 }
4014
4015 guint64 
4016 mono_lldiv_un (guint64 a, guint64 b)
4017 {
4018         return a / b;
4019 }
4020
4021 guint64 
4022 mono_llrem_un (guint64 a, guint64 b)
4023 {
4024         return a % b;
4025 }
4026
4027 MBTree *
4028 mono_ctree_new (MonoMemPool *mp, int op, MBTree *left, MBTree *right)
4029 {
4030         MBTree *t = mono_mempool_alloc0 (mp, sizeof (MBTree));
4031
4032         t->op = op;
4033         t->left = left;
4034         t->right = right;
4035         t->reg1 = -1;
4036         t->reg2 = -1;
4037         t->reg3 = -1;
4038         t->svt = VAL_UNKNOWN;
4039         t->cli_addr = -1;
4040         return t;
4041 }
4042
4043 MBTree *
4044 mono_ctree_new_leaf (MonoMemPool *mp, int op)
4045 {
4046         return mono_ctree_new (mp, op, NULL, NULL);
4047 }
4048
4049 gpointer 
4050 arch_get_lmf_addr (void)
4051 {
4052         gpointer *lmf;
4053
4054         if ((lmf = TlsGetValue (lmf_thread_id)))
4055                 return lmf;
4056
4057         lmf = g_malloc (sizeof (gpointer));
4058         *lmf = NULL;
4059
4060         TlsSetValue (lmf_thread_id, lmf);
4061
4062         return lmf;
4063 }
4064
4065 MonoArray*
4066 mono_array_new_wrapper  (MonoClass *eclass, guint32 n)
4067 {
4068         MonoDomain *domain = mono_domain_get ();
4069
4070         return mono_array_new (domain, eclass, n);
4071 }
4072
4073 MonoObject *
4074 mono_object_new_wrapper (MonoClass *klass)
4075 {
4076         MonoDomain *domain = mono_domain_get ();
4077
4078         return mono_object_new (domain, klass);
4079 }
4080
4081 MonoString*
4082 mono_ldstr_wrapper (MonoImage *image, guint32 ind)
4083 {
4084         MonoDomain *domain = mono_domain_get ();
4085
4086         return mono_ldstr (domain, image, ind);
4087 }
4088
4089 gpointer 
4090 mono_ldsflda (MonoClass *klass, int offset)
4091 {
4092         MonoDomain *domain = mono_domain_get ();
4093         MonoVTable *vt;
4094         gpointer addr;
4095         
4096         vt = mono_class_vtable (domain, klass);
4097         addr = (char*)(vt->data) + offset;
4098
4099         return addr;
4100 }
4101
4102 #ifdef DEBUG
4103 void *
4104 MEMCOPY (void *dest, const void *src, size_t n)
4105 {
4106         int i, l = n;
4107
4108         printf ("MEMCPY(%p to %p [%d]) ", src, dest, n);
4109
4110         for (i = 0; i < l; i++)
4111                 printf ("%02x ", *((guint8 *)src + i));
4112         printf ("\n");
4113         
4114         return memcpy (dest, src, n);
4115 }
4116 #endif
4117