2 * x86.brg: X86 code generator
5 * Dietmar Maurer (dietmar@ximian.com)
7 * (C) 2001 Ximian, Inc.
15 #ifndef PLATFORM_WIN32
17 #include <sys/syscall.h>
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>
32 void print_lmf (void);
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))
40 AMImmediate = 0, // ptr
42 AMIndex = 2, // V[REG*X]
43 AMBaseIndex = 3, // V[REG*X][REG]
56 unsigned last_instr:1;
80 MonoClassField *field;
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);
96 gpointer arch_get_lmf_addr (void);
99 mono_array_new_wrapper (MonoClass *eclass, guint32 n);
101 mono_object_new_wrapper (MonoClass *klass);
103 mono_ldstr_wrapper (MonoImage *image, guint32 ind);
106 get_mono_object_isinst (void);
108 #define MB_OPT_LEVEL 1
110 #if MB_OPT_LEVEL == 0
111 #define MB_USE_OPT1(c) 65535
112 #define MB_USE_OPT2(c) 65535
114 #if MB_OPT_LEVEL == 1
115 #define MB_USE_OPT1(c) c
116 #define MB_USE_OPT2(c) 65535
118 #if MB_OPT_LEVEL >= 2
119 #define MB_USE_OPT1(c) c
120 #define MB_USE_OPT2(c) c
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);
141 #define MEMCOPY debug_memcpy
142 void *MEMCOPY (void *dest, const void *src, size_t n);
144 #define PRINT_REG(text,reg) REAL_PRINT_REG(text,reg)
147 #define MEMCOPY memcpy
149 #define PRINT_REG(x,y)
153 /* The call instruction for virtual functions must have a known
154 * size (used by x86_magic_trampoline)
156 #define x86_call_virtual(inst,basereg,disp) \
158 *(inst)++ = (unsigned char)0xff; \
159 x86_address_byte ((inst), 2, 2, (basereg)); \
160 x86_imm_emit32 ((inst), (disp)); \
163 /* emit an exception if condition is fail */
164 #define EMIT_COND_SYSTEM_EXCEPTION(cond,signed,exc_name) \
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); \
178 # terminal definitions
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
211 # integer constant folding
212 coni4: AND (coni4, coni4) {
213 tree->data.i = tree->left->data.i & tree->right->data.i;
216 coni4: OR (coni4, coni4) {
217 tree->data.i = tree->left->data.i | tree->right->data.i;
220 coni4: XOR (coni4, coni4) {
221 tree->data.i = tree->left->data.i ^ tree->right->data.i;
224 coni4: SHL (coni4, coni4) {
225 tree->data.i = tree->left->data.i << tree->right->data.i;
228 coni4: SHR (coni4, coni4) {
229 tree->data.i = tree->left->data.i >> tree->right->data.i;
233 tree->data.i = ~tree->left->data.i;
236 coni4: ADD (coni4, coni4) {
237 tree->data.i = tree->left->data.i + tree->right->data.i;
240 coni4: SUB (coni4, coni4) {
241 tree->data.i = tree->left->data.i - tree->right->data.i;
244 coni4: MUL (coni4, coni4) {
245 tree->data.i = tree->left->data.i * tree->right->data.i;
248 coni4: DIV (coni4, coni4) {
249 tree->data.i = tree->left->data.i / tree->right->data.i;
251 MBCOND (tree->right->data.i)
255 coni4: REM (coni4, coni4) {
256 tree->data.i = tree->left->data.i % tree->right->data.i;
258 MBCOND (tree->right->data.i)
262 coni4: CEQ (coni4, coni4) {
263 if (tree->left->data.i == tree->right->data.i)
269 coni4: CGT (coni4, coni4) {
270 if (tree->left->data.i > tree->right->data.i)
276 coni4: CLT (coni4, coni4) {
277 if (tree->left->data.i < tree->right->data.i)
292 tree->data.ainfo.offset = tree->data.i;
293 tree->data.ainfo.amode = AMImmediate;
297 tree->data.ainfo.offset = tree->data.i;
298 tree->data.ainfo.amode = AMImmediate;
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;
309 tree->data.ainfo.offset = 0;
310 tree->data.ainfo.basereg = tree->reg1;
311 tree->data.ainfo.amode = AMBase;
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;
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;
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;
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;
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);
347 index: MUL (reg, coni4) {
348 static int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
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];
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);
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;
376 # we pass exception in ECX to catch handler
378 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
380 if (tree->reg1 != X86_ECX)
381 x86_mov_reg_reg (s->code, tree->reg1, X86_ECX, 4);
383 /* store it so that we can RETHROW it later */
384 x86_mov_membase_reg (s->code, X86_EBP, offset, tree->reg1, 4);
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);
397 int off = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
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);
407 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_BB, tree->data.bb);
408 x86_call_imm (s->code, 0);
415 stmt: STIND_I4 (addr, coni4) {
416 switch (tree->left->data.ainfo.amode) {
419 x86_mov_mem_imm (s->code, tree->left->data.ainfo.offset, tree->right->data.i, 4);
423 x86_mov_membase_imm (s->code, tree->left->data.ainfo.basereg,
424 tree->left->data.ainfo.offset, tree->right->data.i, 4);
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);
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);
439 stmt: STIND_I4 (addr, reg) {
440 PRINT_REG ("STIND_I4", tree->right->reg1);
442 switch (tree->left->data.ainfo.amode) {
445 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
449 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
450 tree->left->data.ainfo.offset, tree->right->reg1, 4);
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);
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);
465 stmt: REMOTE_STIND_I4 (reg, reg) {
468 int lreg = tree->left->reg1;
469 int rreg = tree->right->reg1;
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);
482 /* this is a transparent proxy - remote the call */
484 /* save value to stack */
485 x86_push_reg (s->code, rreg);
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);
495 br [1] = s->code; x86_jump8 (s->code, 0);
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);
502 x86_patch (br [1], s->code);
505 stmt: STIND_REF (addr, reg) {
506 PRINT_REG ("STIND_REF", tree->right->reg1);
508 switch (tree->left->data.ainfo.amode) {
511 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
515 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
516 tree->left->data.ainfo.offset, tree->right->reg1, 4);
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);
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);
531 stmt: REMOTE_STIND_REF (reg, reg) {
534 int lreg = tree->left->reg1;
535 int rreg = tree->right->reg1;
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);
548 /* this is a transparent proxy - remote the call */
550 /* save value to stack */
551 x86_push_reg (s->code, rreg);
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);
561 br [1] = s->code; x86_jump8 (s->code, 0);
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);
568 x86_patch (br [1], s->code);
571 stmt: STIND_I1 (addr, reg) {
572 PRINT_REG ("STIND_I1", tree->right->reg1);
574 switch (tree->left->data.ainfo.amode) {
577 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 1);
581 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
582 tree->left->data.ainfo.offset, tree->right->reg1, 1);
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);
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);
597 stmt: REMOTE_STIND_I1 (reg, reg) {
600 int lreg = tree->left->reg1;
601 int rreg = tree->right->reg1;
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);
614 /* this is a transparent proxy - remote the call */
616 /* save value to stack */
617 x86_push_reg (s->code, rreg);
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);
627 br [1] = s->code; x86_jump8 (s->code, 0);
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);
634 x86_patch (br [1], s->code);
637 stmt: STIND_I2 (addr, reg) {
638 PRINT_REG ("STIND_I2", tree->right->reg1);
640 switch (tree->left->data.ainfo.amode) {
643 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 2);
647 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
648 tree->left->data.ainfo.offset, tree->right->reg1, 2);
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);
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);
663 stmt: REMOTE_STIND_I2 (reg, reg) {
666 int lreg = tree->left->reg1;
667 int rreg = tree->right->reg1;
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);
680 /* this is a transparent proxy - remote the call */
682 /* save value to stack */
683 x86_push_reg (s->code, rreg);
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);
693 br [1] = s->code; x86_jump8 (s->code, 0);
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);
700 x86_patch (br [1], s->code);
703 reg: LDIND_I4 (addr) {
705 switch (tree->left->data.ainfo.amode) {
708 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
712 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
713 tree->left->data.ainfo.offset, 4);
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);
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);
727 PRINT_REG ("LDIND_I4", tree->reg1);
730 reg: LDIND_REF (addr) {
732 switch (tree->left->data.ainfo.amode) {
735 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
739 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
740 tree->left->data.ainfo.offset, 4);
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);
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);
754 PRINT_REG ("LDIND_REF", tree->reg1);
757 reg: LDIND_I1 (addr) {
758 switch (tree->left->data.ainfo.amode) {
761 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, FALSE);
765 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
766 tree->left->data.ainfo.offset, TRUE, FALSE);
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);
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);
779 PRINT_REG ("LDIND_I1", tree->reg1);
782 reg: LDIND_U1 (addr) {
783 switch (tree->left->data.ainfo.amode) {
786 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, FALSE);
790 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
791 tree->left->data.ainfo.offset, FALSE, FALSE);
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);
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);
804 PRINT_REG ("LDIND_U1", tree->reg1);
807 reg: LDIND_I2 (addr) {
808 switch (tree->left->data.ainfo.amode) {
811 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, TRUE);
815 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
816 tree->left->data.ainfo.offset, TRUE, TRUE);
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);
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);
829 PRINT_REG ("LDIND_U2", tree->reg1);
832 reg: LDIND_U2 (addr) {
833 switch (tree->left->data.ainfo.amode) {
836 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, TRUE);
840 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
841 tree->left->data.ainfo.offset, FALSE, TRUE);
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);
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);
854 PRINT_REG ("LDIND_U2", tree->reg1);
857 reg: LDIND_U4 (addr) {
858 switch (tree->left->data.ainfo.amode) {
861 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
865 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
866 tree->left->data.ainfo.offset, 4);
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);
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);
879 PRINT_REG ("LDIND_U4", tree->reg1);
882 reg: REMOTE_LDFLDA (reg) {
885 int lreg = tree->left->reg1;
890 if (tree->reg1 != treg)
891 x86_push_reg (s->code, treg);
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);
897 /* this is a transparent proxy - remote the call */
899 x86_push_reg (s->code, X86_EAX);
901 x86_push_reg (s->code, X86_EDX);
902 x86_push_reg (s->code, X86_ECX);
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);
913 x86_mov_reg_reg (s->code, treg, X86_EAX, 4);
915 x86_pop_reg (s->code, X86_ECX);
917 x86_pop_reg (s->code, X86_EDX);
919 x86_pop_reg (s->code, X86_EAX);
921 x86_mov_reg_reg (s->code, tree->reg1, treg, 4);
923 br [1] = s->code; x86_jump8 (s->code, 0);
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));
930 x86_lea_membase (s->code, tree->reg1, lreg, tree->data.fi.field->offset);
932 x86_patch (br [1], s->code);
934 if (tree->reg1 != treg)
935 x86_pop_reg (s->code, treg);
939 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
941 x86_lea_membase (s->code, tree->reg1, X86_EBP, offset);
943 PRINT_REG ("ADDR_L", tree->reg1);
948 x86_mov_reg_imm (s->code, tree->reg1, tree->data.p);
952 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
956 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
960 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
964 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
967 # warning: this chain rule requires a register
969 x86_mov_reg_imm (s->code, tree->reg1, tree->data.i);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
1070 reg: MUL (reg, reg) {
1071 x86_imul_reg_reg (s->code, tree->left->reg1, tree->right->reg1);
1073 if (tree->reg1 != tree->left->reg1)
1074 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
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");
1081 if (tree->reg1 != tree->left->reg1)
1082 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1085 reg: MUL_OVF_UN (reg, reg) {
1086 mono_assert (tree->right->reg1 != X86_EAX);
1088 if (tree->left->reg1 != X86_EAX)
1089 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1091 x86_mul_reg (s->code, tree->right->reg1, FALSE);
1092 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
1094 mono_assert (tree->reg1 == X86_EAX &&
1095 tree->reg2 == X86_EDX);
1098 reg: DIV (reg, reg) {
1099 mono_assert (tree->right->reg1 != X86_EAX);
1101 if (tree->left->reg1 != X86_EAX)
1102 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1105 x86_div_reg (s->code, tree->right->reg1, TRUE);
1107 mono_assert (tree->reg1 == X86_EAX &&
1108 tree->reg2 == X86_EDX);
1111 reg: DIV_UN (reg, reg) {
1112 mono_assert (tree->right->reg1 != X86_EAX);
1114 if (tree->left->reg1 != X86_EAX)
1115 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1117 x86_mov_reg_imm (s->code, X86_EDX, 0);
1118 x86_div_reg (s->code, tree->right->reg1, FALSE);
1120 mono_assert (tree->reg1 == X86_EAX &&
1121 tree->reg2 == X86_EDX);
1124 reg: REM (reg, reg) {
1125 mono_assert (tree->right->reg1 != X86_EAX);
1126 mono_assert (tree->right->reg1 != X86_EDX);
1128 if (tree->left->reg1 != X86_EAX)
1129 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1131 /* sign extend to 64bit in EAX/EDX */
1133 x86_div_reg (s->code, tree->right->reg1, TRUE);
1134 x86_mov_reg_reg (s->code, X86_EAX, X86_EDX, 4);
1136 mono_assert (tree->reg1 == X86_EAX &&
1137 tree->reg2 == X86_EDX);
1140 reg: REM_UN (reg, reg) {
1141 mono_assert (tree->right->reg1 != X86_EAX);
1142 mono_assert (tree->right->reg1 != X86_EDX);
1144 if (tree->left->reg1 != X86_EAX)
1145 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
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);
1152 mono_assert (tree->reg1 == X86_EAX &&
1153 tree->reg2 == X86_EDX);
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);
1160 x86_alu_reg_imm (s->code, X86_ADD, tree->left->reg1, tree->right->data.i);
1162 if (tree->reg1 != tree->left->reg1)
1163 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1167 reg: ADD (reg, reg) {
1168 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
1170 if (tree->reg1 != tree->left->reg1)
1171 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
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");
1178 if (tree->reg1 != tree->left->reg1)
1179 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
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");
1186 if (tree->reg1 != tree->left->reg1)
1187 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
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);
1194 x86_alu_reg_imm (s->code, X86_SUB, tree->left->reg1, tree->right->data.i);
1196 if (tree->reg1 != tree->left->reg1)
1197 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1200 reg: SUB (reg, reg) {
1201 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
1203 if (tree->reg1 != tree->left->reg1)
1204 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
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");
1211 if (tree->reg1 != tree->left->reg1)
1212 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
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");
1219 if (tree->reg1 != tree->left->reg1)
1220 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
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);
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);
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);
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);
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);
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);
1259 reg: AND (reg, reg) {
1260 x86_alu_reg_reg (s->code, X86_AND, tree->left->reg1, tree->right->reg1);
1262 if (tree->reg1 != tree->left->reg1)
1263 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1266 reg: OR (reg, reg) {
1267 x86_alu_reg_reg (s->code, X86_OR, tree->left->reg1, tree->right->reg1);
1269 if (tree->reg1 != tree->left->reg1)
1270 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1273 reg: XOR (reg, reg) {
1274 x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->right->reg1);
1276 if (tree->reg1 != tree->left->reg1)
1277 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1281 x86_neg_reg (s->code, tree->left->reg1);
1283 if (tree->reg1 != tree->left->reg1)
1284 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1288 x86_not_reg (s->code, tree->left->reg1);
1290 if (tree->reg1 != tree->left->reg1)
1291 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1294 reg: SHL (reg, coni4) {
1295 x86_shift_reg_imm (s->code, X86_SHL, tree->left->reg1, tree->right->data.i);
1297 if (tree->reg1 != tree->left->reg1)
1298 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
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);
1306 if (tree->reg1 != tree->left->reg1)
1307 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1309 mono_assert (tree->reg1 != X86_ECX &&
1310 tree->left->reg1 != X86_ECX);
1313 reg: SHR (reg, coni4) {
1314 x86_shift_reg_imm (s->code, X86_SAR, tree->left->reg1, tree->right->data.i);
1316 if (tree->reg1 != tree->left->reg1)
1317 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
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);
1325 if (tree->reg1 != tree->left->reg1)
1326 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1328 mono_assert (tree->reg1 != X86_ECX &&
1329 tree->left->reg1 != X86_ECX);
1332 reg: SHR_UN (reg, coni4) {
1333 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg1, tree->right->data.i);
1335 if (tree->reg1 != tree->left->reg1)
1336 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
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);
1344 if (tree->reg1 != tree->left->reg1)
1345 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1347 mono_assert (tree->reg1 != X86_ECX &&
1348 tree->left->reg1 != X86_ECX);
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);
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);
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);
1373 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
1374 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NE, TRUE, "NullReferenceException");
1376 x86_mov_reg_membase (s->code, tree->reg1, tree->left->reg1,
1377 G_STRUCT_OFFSET (MonoArray, max_length), 4);
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");
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]);
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));
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);
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);
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);
1416 PRINT_REG ("LDSTR", tree->reg1);
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);
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);
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);
1438 PRINT_REG ("NEWARR", tree->reg1);
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);
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);
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);
1460 PRINT_REG ("NEWARR_SPEC", tree->reg1);
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);
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));
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);
1480 PRINT_REG ("NEWOBJ", tree->reg1);
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);
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));
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);
1500 PRINT_REG ("NEWOBJ_SPEC", tree->reg1);
1504 int size = tree->data.i;
1507 mono_assert (size > 0);
1512 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);
1513 x86_mov_reg_reg (s->code, tree->reg1, X86_ESP, 4);
1517 if (tree->reg1 != tree->left->reg1)
1518 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1520 x86_test_reg_reg (s->code, tree->reg1, tree->reg1);
1521 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NE, TRUE, "NullReferenceException");
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));
1533 reg: CASTCLASS (reg) {
1534 MonoClass *klass = tree->data.klass;
1536 int lreg = tree->left->reg1;
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);
1542 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1543 /* lreg = obj->vtable */
1544 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
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");
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);
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");
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);
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,
1582 x86_patch (br [1], s->code);
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");
1592 x86_patch (br [0], s->code);
1593 x86_pop_reg (s->code, tree->reg1);
1597 MonoClass *klass = tree->data.klass;
1599 int lreg = tree->left->reg1;
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);
1605 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1606 /* lreg = obj->vtable */
1607 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
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);
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);
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);
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);
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,
1651 x86_patch (br [1], s->code);
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);
1663 x86_patch (br [0], s->code);
1664 x86_pop_reg (s->code, tree->reg1);
1667 stmt: INITOBJ (reg) {
1672 if (i == 1 || i == 2 || i == 4) {
1673 x86_mov_membase_imm (s->code, tree->left->reg1, 0, 0, i);
1677 i = tree->data.i / 4;
1678 j = tree->data.i % 4;
1680 x86_push_reg (s->code, X86_EAX);
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);
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);
1692 x86_prefix (s->code, X86_REP_PREFIX);
1693 x86_stosl (s->code);
1694 x86_pop_reg (s->code, X86_ECX);
1696 for (i = 0; i < j; i++)
1697 x86_stosb (s->code);
1701 x86_mov_membase_imm (s->code, X86_EDI, 0, 0, 2);
1702 x86_mov_membase_imm (s->code, X86_EDI, 2, 0, 1);
1707 if (tree->left->reg1 != X86_EDI)
1708 x86_pop_reg (s->code, X86_EDI);
1710 x86_pop_reg (s->code, X86_EAX);
1718 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_BB, tree->data.bb);
1719 x86_jump32 (s->code, 0);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
1855 x86_breakpoint (s->code);
1859 if (tree->left->reg1 != X86_EAX)
1860 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
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);
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);
1876 stmt: ARG_I4 (LDIND_I4 (addr)) {
1877 MBTree *at = tree->left->left;
1879 switch (at->data.ainfo.amode) {
1882 x86_push_mem (s->code, at->data.ainfo.offset);
1886 x86_push_membase (s->code, at->data.ainfo.basereg, at->data.ainfo.offset);
1889 x86_push_memindex (s->code, X86_NOBASEREG, at->data.ainfo.offset,
1890 at->data.ainfo.indexreg, at->data.ainfo.shift);
1893 x86_push_memindex (s->code, at->data.ainfo.basereg,
1894 at->data.ainfo.offset, at->data.ainfo.indexreg,
1895 at->data.ainfo.shift);
1900 stmt: ARG_I4 (LDIND_U4 (addr)) {
1901 MBTree *at = tree->left->left;
1903 switch (at->data.ainfo.amode) {
1906 x86_push_mem (s->code, at->data.ainfo.offset);
1910 x86_push_membase (s->code, at->data.ainfo.basereg, at->data.ainfo.offset);
1913 x86_push_memindex (s->code, X86_NOBASEREG, at->data.ainfo.offset,
1914 at->data.ainfo.indexreg, at->data.ainfo.shift);
1917 x86_push_memindex (s->code, at->data.ainfo.basereg,
1918 at->data.ainfo.offset, at->data.ainfo.indexreg,
1919 at->data.ainfo.shift);
1924 stmt: ARG_I4 (reg) {
1925 x86_push_reg (s->code, tree->left->reg1);
1926 PRINT_REG ("ARG_I4", tree->left->reg1);
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);
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);
1941 x86_mov_membase_reg (s->code, X86_ESP, 12, X86_EAX, 4);
1943 x86_pop_reg (s->code, X86_EDX);
1944 x86_pop_reg (s->code, X86_ECX);
1945 x86_pop_reg (s->code, X86_EAX);
1948 stmt: ARG_I4 (ADDR_G) {
1949 x86_push_imm (s->code, tree->left->data.p);
1952 stmt: ARG_I4 (coni4) "MB_USE_OPT1(0)" {
1953 x86_push_imm (s->code, tree->left->data.i);
1957 PRINT_REG ("THIS", tree->reg1);
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);
1968 stmt: CHECKTHIS (reg) {
1969 x86_alu_membase_imm (s->code, X86_CMP, tree->left->reg1, 0, 0);
1974 reg: CALL_I4 (this, reg) {
1976 int lreg = tree->left->reg1;
1977 int rreg = tree->right->reg1;
1979 if (lreg == treg || rreg == treg)
1981 if (lreg == treg || rreg == treg)
1983 if (lreg == treg || rreg == treg)
1984 mono_assert_not_reached ();
1986 if (tree->left->op != MB_TERM_NOP) {
1987 mono_assert (lreg >= 0);
1988 x86_push_reg (s->code, lreg);
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);
1997 x86_call_reg (s->code, rreg);
1999 if (tree->data.ci.args_size)
2000 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2002 PRINT_REG ("CALL_I4", tree->reg1);
2004 mono_assert (tree->reg1 == X86_EAX);
2007 reg: CALL_I4 (this, ADDR_G) {
2008 int lreg = tree->left->reg1;
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);
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);
2026 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, tree->right->data.p);
2027 x86_call_code (s->code, 0);
2029 if (tree->data.ci.args_size)
2030 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2032 PRINT_REG ("CALL_I4", tree->reg1);
2034 mono_assert (tree->reg1 == X86_EAX);
2037 reg: LDVIRTFTN (reg, INTF_ADDR) {
2038 int lreg = tree->left->reg1;
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);
2047 reg: CALL_I4 (this, INTF_ADDR) {
2048 int lreg = tree->left->reg1;
2054 if (tree->left->op != MB_TERM_NOP) {
2055 mono_assert (lreg >= 0);
2056 x86_push_reg (s->code, lreg);
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);
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);
2071 if (tree->data.ci.args_size)
2072 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2074 PRINT_REG ("CALL_I4(INTERFACE)", tree->reg1);
2076 mono_assert (tree->reg1 == X86_EAX);
2079 reg: LDVIRTFTN (reg, VFUNC_ADDR) {
2080 int lreg = tree->left->reg1;
2082 x86_mov_reg_membase (s->code, tree->reg1, lreg, 0, 4);
2084 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2), 4);
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);
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));
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);
2104 PRINT_REG ("LDFTN", tree->reg1);
2108 reg: CALL_I4 (this, VFUNC_ADDR) {
2109 int lreg = tree->left->reg1;
2115 if (tree->left->op != MB_TERM_NOP) {
2116 mono_assert (lreg >= 0);
2117 x86_push_reg (s->code, lreg);
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);
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));
2130 if (tree->data.ci.args_size)
2131 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2133 PRINT_REG ("CALL_I4(VIRTUAL)", tree->reg1);
2135 mono_assert (tree->reg1 == X86_EAX);
2138 stmt: CALL_VOID (this, ADDR_G) {
2139 int lreg = tree->left->reg1;
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);
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);
2157 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, tree->right->data.p);
2158 x86_call_code (s->code, 0);
2160 if (tree->data.ci.args_size)
2161 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2164 stmt: CALL_VOID (this, INTF_ADDR) {
2165 int lreg = tree->left->reg1;
2171 if (tree->left->op != MB_TERM_NOP) {
2172 mono_assert (lreg >= 0);
2173 x86_push_reg (s->code, lreg);
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);
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);
2188 if (tree->data.ci.args_size)
2189 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2192 stmt: CALL_VOID (this, VFUNC_ADDR) {
2193 int lreg = tree->left->reg1;
2199 if (tree->left->op != MB_TERM_NOP) {
2200 mono_assert (lreg >= 0);
2201 x86_push_reg (s->code, lreg);
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);
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));
2214 if (tree->data.ci.args_size)
2215 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2218 stmt: SWITCH (reg) {
2220 guint32 *jt = (guint32 *)tree->data.p;
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);
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);
2235 reg: CONV_I1 (lreg) {
2236 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
2239 reg: CONV_I2 (lreg) {
2240 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
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);
2249 reg: CONV_OVF_I4 (lreg){
2250 guint8 *start = s->code;
2251 guchar* o1, *o2, *o3, *o4, *o5;
2255 * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000
2257 for (i = 0; i < 2; i++) {
2260 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
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);
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);
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);
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);
2282 /* nope, emit exception */
2283 x86_branch8 (s->code, X86_CC_NE, o2 - o5, TRUE);
2286 if (tree->reg1 != tree->left->reg1)
2287 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2290 reg: CONV_OVF_I4 (lreg){
2291 guint8 *br [3], *label [1];
2294 * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000
2296 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
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);
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;
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);
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);
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]);
2321 if (tree->reg1 != tree->left->reg1)
2322 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
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);
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);
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));
2350 lreg: CONV_I8 (coni4) {
2351 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
2353 if (tree->left->data.i >= 0)
2354 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2356 x86_mov_reg_imm (s->code, tree->reg2, -1);
2359 lreg: CONV_I8 (reg) {
2362 if (tree->reg1 != tree->left->reg1)
2363 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
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);
2369 x86_mov_reg_imm (s->code, tree->reg2, -1);
2370 mono_assert ((s->code - i1) == 5);
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);
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);
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);
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);
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);
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");
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);
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);
2417 stmt: STIND_I8 (addr, lreg) {
2419 switch (tree->left->data.ainfo.amode) {
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);
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);
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);
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);
2452 stmt: REMOTE_STIND_I8 (reg, lreg) {
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);
2461 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
2463 /* this is a transparent proxy - remote the call */
2465 /* save value to stack */
2466 x86_push_reg (s->code, tree->right->reg2);
2467 x86_push_reg (s->code, tree->right->reg1);
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);
2477 br [1] = s->code; x86_jump8 (s->code, 0);
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);
2485 x86_patch (br [1], s->code);
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) {
2493 switch (tree->left->data.ainfo.amode) {
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);
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);
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);
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);
2520 PRINT_REG ("LDIND_I8_0", tree->reg1);
2521 PRINT_REG ("LDIND_I8_1", tree->reg2);
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 */
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 */
2557 lreg: SHR (lreg, reg) {
2560 if (tree->right->reg1 != X86_ECX)
2561 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
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);
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);
2577 lreg: SHR_UN (lreg, reg) {
2580 if (tree->right->reg1 != X86_ECX)
2581 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
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);
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);
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 */
2612 lreg: SHL (lreg, reg) {
2615 if (tree->right->reg1 != X86_ECX)
2616 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
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);
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);
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);
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);
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");
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);
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");
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);
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);
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);
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");
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);
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");
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
2743 x86_not_reg (s->code, tree->reg1);
2744 x86_not_reg (s->code, tree->reg2);
2747 lreg: MUL (lreg, lreg) {
2748 if (mono_regset_reg_used (s->rs, X86_ECX))
2749 x86_push_reg (s->code, X86_ECX);
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);
2759 if (mono_regset_reg_used (s->rs, X86_ECX))
2760 x86_pop_reg (s->code, X86_ECX);
2762 mono_assert (tree->reg1 == X86_EAX &&
2763 tree->reg2 == X86_EDX);
2766 lreg: MUL_OVF (lreg, lreg) {
2767 if (mono_regset_reg_used (s->rs, X86_ECX))
2768 x86_push_reg (s->code, X86_ECX);
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);
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);
2789 if (mono_regset_reg_used (s->rs, X86_ECX))
2790 x86_pop_reg (s->code, X86_ECX);
2792 mono_assert (tree->reg1 == X86_EAX &&
2793 tree->reg2 == X86_EDX);
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);
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);
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);
2819 if (mono_regset_reg_used (s->rs, X86_ECX))
2820 x86_pop_reg (s->code, X86_ECX);
2822 mono_assert (tree->reg1 == X86_EAX &&
2823 tree->reg2 == X86_EDX);
2826 lreg: DIV (lreg, lreg) {
2827 if (mono_regset_reg_used (s->rs, X86_ECX))
2828 x86_push_reg (s->code, X86_ECX);
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);
2838 if (mono_regset_reg_used (s->rs, X86_ECX))
2839 x86_pop_reg (s->code, X86_ECX);
2841 mono_assert (tree->reg1 == X86_EAX &&
2842 tree->reg2 == X86_EDX);
2845 lreg: REM (lreg, lreg) {
2846 if (mono_regset_reg_used (s->rs, X86_ECX))
2847 x86_push_reg (s->code, X86_ECX);
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);
2857 if (mono_regset_reg_used (s->rs, X86_ECX))
2858 x86_pop_reg (s->code, X86_ECX);
2860 mono_assert (tree->reg1 == X86_EAX &&
2861 tree->reg2 == X86_EDX);
2864 lreg: DIV_UN (lreg, lreg) {
2865 if (mono_regset_reg_used (s->rs, X86_ECX))
2866 x86_push_reg (s->code, X86_ECX);
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);
2876 if (mono_regset_reg_used (s->rs, X86_ECX))
2877 x86_pop_reg (s->code, X86_ECX);
2879 mono_assert (tree->reg1 == X86_EAX &&
2880 tree->reg2 == X86_EDX);
2883 lreg: REM_UN (lreg, lreg) {
2884 if (mono_regset_reg_used (s->rs, X86_ECX))
2885 x86_push_reg (s->code, X86_ECX);
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);
2895 if (mono_regset_reg_used (s->rs, X86_ECX))
2896 x86_pop_reg (s->code, X86_ECX);
2898 mono_assert (tree->reg1 == X86_EAX &&
2899 tree->reg2 == X86_EDX);
2902 lreg: CALL_I8 (this, ADDR_G) {
2903 int lreg = tree->left->reg1;
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);
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);
2921 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, tree->right->data.p);
2922 x86_call_code (s->code, 0);
2924 if (tree->data.ci.args_size)
2925 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2927 mono_assert (tree->reg1 == X86_EAX);
2928 mono_assert (tree->reg2 == X86_EDX);
2931 lreg: CALL_I8 (this, VFUNC_ADDR) {
2932 int lreg = tree->left->reg1;
2938 if (tree->left->op != MB_TERM_NOP) {
2939 mono_assert (lreg >= 0);
2940 x86_push_reg (s->code, lreg);
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);
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));
2953 if (tree->data.ci.args_size)
2954 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2956 PRINT_REG ("CALL0_I8(VIRTUAL)", tree->reg1);
2957 PRINT_REG ("CALL1_I8(VIRTUAL)", tree->reg2);
2959 mono_assert (tree->reg1 == X86_EAX);
2960 mono_assert (tree->reg2 == X86_EDX);
2963 lreg: CALL_I8 (this, INTF_ADDR) {
2964 int lreg = tree->left->reg1;
2970 if (tree->left->op != MB_TERM_NOP) {
2971 mono_assert (lreg >= 0);
2972 x86_push_reg (s->code, lreg);
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);
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);
2987 if (tree->data.ci.args_size)
2988 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2990 PRINT_REG ("CALL_I8(INTERFACE)", tree->reg1);
2992 mono_assert (tree->reg1 == X86_EAX);
2993 mono_assert (tree->reg2 == X86_EDX);
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);
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);
3007 } else if (tree->left->reg2 != X86_EDX) {
3008 x86_mov_reg_reg (s->code, X86_EDX, tree->left->reg2, 4);
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);
3018 stmt: ARG_I8 (lreg) {
3019 x86_push_reg (s->code, tree->left->reg2);
3020 x86_push_reg (s->code, tree->left->reg1);
3023 reg: CEQ (lreg, lreg) {
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);
3034 reg: CLT (lreg, lreg) {
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);
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);
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);
3053 x86_patch (br [3], s->code);
3056 reg: CLT_UN (lreg, lreg) {
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);
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);
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);
3075 x86_patch (br [3], s->code);
3078 reg: CGT (lreg, lreg) {
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);
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);
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);
3097 x86_patch (br [3], s->code);
3100 reg: CGT_UN (lreg, lreg) {
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);
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);
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);
3119 x86_patch (br [3], s->code);
3122 stmt: BEQ (lreg, lreg) {
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);
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);
3143 stmt: BGE (lreg, lreg) {
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);
3157 stmt: BGE_UN (lreg, lreg) {
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);
3171 stmt: BGT (lreg, lreg) {
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);
3185 stmt: BGT_UN (lreg, lreg) {
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);
3199 stmt: BLT (lreg, lreg) {
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);
3213 stmt: BLT_UN (lreg, lreg) {
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);
3227 stmt: BLE (lreg, lreg) {
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);
3241 stmt: BLE_UN (lreg, lreg) {
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);
3258 #stmt: STLOC (CONV_I4 (freg)) {
3260 # x86_fist_pop_membase (s->code, X86_EBP, tree->data.i, FALSE);
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);
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);
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);
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);
3322 reg: CEQ (freg, freg) {
3323 int treg = tree->reg1;
3325 if (treg != X86_EAX)
3326 x86_push_reg (s->code, X86_EAX); // save EAX
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);
3335 if (treg != X86_EAX)
3336 x86_pop_reg (s->code, X86_EAX); // save EAX
3339 reg: CGT (freg, freg) {
3340 int treg = tree->reg1;
3342 if (treg != X86_EAX)
3343 x86_push_reg (s->code, X86_EAX); // save EAX
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);
3352 if (treg != X86_EAX)
3353 x86_pop_reg (s->code, X86_EAX); // save EAX
3356 reg: CGT_UN (freg, freg) {
3357 int treg = tree->reg1;
3359 if (treg != X86_EAX)
3360 x86_push_reg (s->code, X86_EAX); // save EAX
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);
3369 if (treg != X86_EAX)
3370 x86_pop_reg (s->code, X86_EAX); // save EAX
3373 reg: CLT (freg, freg) {
3374 int treg = tree->reg1;
3376 if (treg != X86_EAX)
3377 x86_push_reg (s->code, X86_EAX); // save EAX
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);
3385 if (treg != X86_EAX)
3386 x86_pop_reg (s->code, X86_EAX); // save EAX
3389 reg: CLT_UN (freg, freg) {
3390 int treg = tree->reg1;
3392 if (treg != X86_EAX)
3393 x86_push_reg (s->code, X86_EAX); // save EAX
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);
3401 if (treg != X86_EAX)
3402 x86_pop_reg (s->code, X86_EAX); // save EAX
3405 freg: CONV_R8 (freg) {
3409 freg: CONV_R4 (freg) {
3410 /* fixme: nothing to do ??*/
3413 freg: CONV_R8 (LDIND_I4 (ADDR_G)) {
3414 x86_fild (s->code, tree->left->left->data.p, FALSE);
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);
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);
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);
3436 freg: CONV_R_UN (lreg) {
3437 static guint8 mn[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x40 };
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);
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);
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);
3458 x86_patch (br [0], s->code);
3460 x86_fld80_membase (s->code, X86_ESP, 0);
3461 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
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);
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);
3479 float f = *(float *)tree->data.p;
3486 x86_fld (s->code, tree->data.p, FALSE);
3490 double d = *(double *)tree->data.p;
3497 x86_fld (s->code, tree->data.p, TRUE);
3500 freg: LDIND_R4 (reg) {
3501 x86_fld_membase (s->code, tree->left->reg1, 0, FALSE);
3504 freg: LDIND_R8 (reg) {
3505 x86_fld_membase (s->code, tree->left->reg1, 0, TRUE);
3508 freg: ADD (freg, freg) {
3509 x86_fp_op_reg (s->code, X86_FADD, 1, TRUE);
3512 freg: SUB (freg, freg) {
3513 x86_fp_op_reg (s->code, X86_FSUB, 1, TRUE);
3516 freg: MUL (freg, freg) {
3517 x86_fp_op_reg (s->code, X86_FMUL, 1, TRUE);
3520 freg: DIV (freg, freg) {
3521 x86_fp_op_reg (s->code, X86_FDIV, 1, TRUE);
3524 freg: REM (freg, freg) {
3527 /* we need to exchange ST(0) with ST(1) */
3528 x86_fxch (s->code, 1);
3530 /* this requires a loop, because fprem1 somtimes
3531 * returns a partial remainder */
3533 x86_fprem1 (s->code);
3534 x86_fnstsw (s->code);
3535 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x0400);
3537 x86_branch8 (s->code, X86_CC_NE, l1 - l2, FALSE);
3540 x86_fstp (s->code, 1);
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);
3554 stmt: STIND_R4 (reg, freg) {
3555 x86_fst_membase (s->code, tree->left->reg1, 0, FALSE, TRUE);
3558 stmt: REMOTE_STIND_R4 (reg, freg) {
3561 int lreg = tree->left->reg1;
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);
3571 /* this is a transparent proxy - remote the call */
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);
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);
3585 br [1] = s->code; x86_jump8 (s->code, 0);
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);
3592 x86_patch (br [1], s->code);
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);
3600 stmt: STIND_R8 (reg, freg) {
3601 x86_fst_membase (s->code, tree->left->reg1, 0, TRUE, TRUE);
3604 stmt: REMOTE_STIND_R8 (reg, freg) {
3607 int lreg = tree->left->reg1;
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);
3617 /* this is a transparent proxy - remote the call */
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);
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);
3631 br [1] = s->code; x86_jump8 (s->code, 0);
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);
3638 x86_patch (br [1], s->code);
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);
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);
3651 # fixme: we need to implement unordered and ordered compares
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
3740 freg: CALL_R8 (this, ADDR_G) {
3741 int lreg = tree->left->reg1;
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);
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);
3759 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, tree->right->data.p);
3760 x86_call_code (s->code, 0);
3762 if (tree->data.ci.args_size)
3763 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
3766 freg: CALL_R8 (this, INTF_ADDR) {
3767 int lreg = tree->left->reg1;
3773 if (tree->left->op != MB_TERM_NOP) {
3774 mono_assert (lreg >= 0);
3775 x86_push_reg (s->code, lreg);
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);
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);
3790 if (tree->data.ci.args_size)
3791 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
3794 freg: CALL_R8 (this, VFUNC_ADDR) {
3795 int lreg = tree->left->reg1;
3801 if (tree->left->op != MB_TERM_NOP) {
3802 mono_assert (lreg >= 0);
3803 x86_push_reg (s->code, lreg);
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);
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));
3816 if (tree->data.ci.args_size)
3817 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
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);
3827 # support for value types
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);
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);
3844 stmt: REMOTE_STIND_OBJ (reg, reg) {
3847 int lreg = tree->left->reg1;
3848 int rreg = tree->right->reg1;
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);
3861 /* this is a transparent proxy - remote the call */
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);
3871 br [1] = s->code; x86_jump8 (s->code, 0);
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;
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);
3885 x86_patch (br [1], s->code);
3887 /* please test this first */
3888 g_assert_not_reached ();
3891 stmt: ARG_OBJ (coni4) {
3892 x86_push_imm (s->code, tree->left->data.i);
3895 stmt: ARG_OBJ (reg) {
3896 int size = tree->data.i;
3899 mono_assert (size > 0);
3904 /* reserve space for the argument */
3905 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);
3907 x86_push_reg (s->code, X86_EAX);
3908 x86_push_reg (s->code, X86_EDX);
3909 x86_push_reg (s->code, X86_ECX);
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);
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);
3920 x86_pop_reg (s->code, X86_ECX);
3921 x86_pop_reg (s->code, X86_EDX);
3922 x86_pop_reg (s->code, X86_EAX);
3925 stmt: RET_OBJ (reg) {
3926 int size = tree->data.i;
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);
3933 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, MEMCOPY);
3934 x86_call_code (s->code, 0);
3936 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
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);
3949 mono_llmult (gint64 a, gint64 b)
3955 mono_llmult_ovf_un (gpointer *exc, guint32 al, guint32 ah, guint32 bl, guint32 bh)
3959 // fixme: this is incredible slow
3962 goto raise_exception;
3964 res = (guint64)al * (guint64)bl;
3966 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
3968 if (t1 > 0xffffffff)
3969 goto raise_exception;
3971 res += ((guint64)t1) << 32;
3977 *exc = mono_get_exception_overflow ();
3982 mono_llmult_ovf (gpointer *exc, guint32 al, gint32 ah, guint32 bl, gint32 bh)
3986 // fixme: check for overflow
3988 res = (gint64)al * (gint64)bl;
3990 t1 = (gint64)ah * bl + al * (gint64)bh;
3992 res += ((gint64)t1) << 32;
3998 *exc = mono_get_exception_overflow ();
4004 mono_lldiv (gint64 a, gint64 b)
4010 mono_llrem (gint64 a, gint64 b)
4016 mono_lldiv_un (guint64 a, guint64 b)
4022 mono_llrem_un (guint64 a, guint64 b)
4028 mono_ctree_new (MonoMemPool *mp, int op, MBTree *left, MBTree *right)
4030 MBTree *t = mono_mempool_alloc0 (mp, sizeof (MBTree));
4038 t->svt = VAL_UNKNOWN;
4044 mono_ctree_new_leaf (MonoMemPool *mp, int op)
4046 return mono_ctree_new (mp, op, NULL, NULL);
4050 arch_get_lmf_addr (void)
4054 if ((lmf = TlsGetValue (lmf_thread_id)))
4057 lmf = g_malloc (sizeof (gpointer));
4060 TlsSetValue (lmf_thread_id, lmf);
4066 mono_array_new_wrapper (MonoClass *eclass, guint32 n)
4068 MonoDomain *domain = mono_domain_get ();
4070 return mono_array_new (domain, eclass, n);
4074 mono_object_new_wrapper (MonoClass *klass)
4076 MonoDomain *domain = mono_domain_get ();
4078 return mono_object_new (domain, klass);
4082 mono_ldstr_wrapper (MonoImage *image, guint32 ind)
4084 MonoDomain *domain = mono_domain_get ();
4086 return mono_ldstr (domain, image, ind);
4090 mono_ldsflda (MonoClass *klass, int offset)
4092 MonoDomain *domain = mono_domain_get ();
4096 vt = mono_class_vtable (domain, klass);
4097 addr = (char*)(vt->data) + offset;
4104 MEMCOPY (void *dest, const void *src, size_t n)
4108 printf ("MEMCPY(%p to %p [%d]) ", src, dest, n);
4110 for (i = 0; i < l; i++)
4111 printf ("%02x ", *((guint8 *)src + i));
4114 return memcpy (dest, src, n);