2 * x86.brg: X86 code generator
5 * Dietmar Maurer (dietmar@ximian.com)
7 * (C) 2001 Ximian, Inc.
16 #ifndef PLATFORM_WIN32
18 #include <sys/syscall.h>
21 #include <mono/metadata/blob.h>
22 #include <mono/metadata/metadata.h>
23 #include <mono/metadata/loader.h>
24 #include <mono/metadata/object.h>
25 #include <mono/metadata/tabledefs.h>
26 #include <mono/metadata/appdomain.h>
27 #include <mono/arch/x86/x86-codegen.h>
33 * Pull the list of opcodes
35 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
39 #include "mono/cil/opcode.def"
44 void print_lmf (void);
46 #define MBTREE_TYPE MBTree
47 #define MBCGEN_TYPE MonoFlowGraph
48 #define MBCOST_DATA MonoFlowGraph
49 #define MBALLOC_STATE mono_mempool_alloc (data->mp, sizeof (MBState))
52 AMImmediate = 0, // ptr
54 AMIndex = 2, // V[REG*X]
55 AMBaseIndex = 3, // V[REG*X][REG]
68 unsigned last_instr:1;
91 MonoClassField *field;
99 gint64 mono_llmult (gint64 a, gint64 b);
100 guint64 mono_llmult_ovf (gpointer *exc, guint32 al, gint32 ah, guint32 bl, gint32 bh);
101 guint64 mono_llmult_ovf_un (gpointer *exc, guint32 al, guint32 ah, guint32 bl, guint32 bh);
102 gint64 mono_lldiv (gint64 a, gint64 b);
103 gint64 mono_llrem (gint64 a, gint64 b);
104 guint64 mono_lldiv_un (guint64 a, guint64 b);
105 guint64 mono_llrem_un (guint64 a, guint64 b);
106 gpointer mono_ldsflda (MonoClass *klass, int offset);
108 void mono_emit_fast_iconv(MBCGEN_TYPE* s, MBTREE_TYPE* tree);
109 void mono_emit_fast_iconv_i8(MBCGEN_TYPE* s, MBTREE_TYPE* tree);
112 mono_array_new_wrapper (MonoClass *eclass, guint32 n);
114 mono_object_new_wrapper (MonoClass *klass);
116 mono_ldstr_wrapper (MonoImage *image, guint32 ind);
119 get_mono_object_isinst (void);
121 #define MB_OPT_LEVEL 1
123 #if MB_OPT_LEVEL == 0
124 #define MB_USE_OPT1(c) 65535
125 #define MB_USE_OPT2(c) 65535
127 #if MB_OPT_LEVEL == 1
128 #define MB_USE_OPT1(c) c
129 #define MB_USE_OPT2(c) 65535
131 #if MB_OPT_LEVEL >= 2
132 #define MB_USE_OPT1(c) c
133 #define MB_USE_OPT2(c) c
138 #define REAL_PRINT_REG(text,reg) \
139 mono_assert (reg >= 0); \
140 x86_push_reg (s->code, X86_EAX); \
141 x86_push_reg (s->code, X86_EDX); \
142 x86_push_reg (s->code, X86_ECX); \
143 x86_push_reg (s->code, reg); \
144 x86_push_imm (s->code, reg); \
145 x86_push_imm (s->code, text " %d %p\n"); \
146 x86_mov_reg_imm (s->code, X86_EAX, printf); \
147 x86_call_reg (s->code, X86_EAX); \
148 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 3*4); \
149 x86_pop_reg (s->code, X86_ECX); \
150 x86_pop_reg (s->code, X86_EDX); \
151 x86_pop_reg (s->code, X86_EAX);
154 #define MEMCOPY debug_memcpy
155 void *MEMCOPY (void *dest, const void *src, size_t n);
157 #define PRINT_REG(text,reg) REAL_PRINT_REG(text,reg)
160 #define MEMCOPY memcpy
162 #define PRINT_REG(x,y)
166 /* The call instruction for virtual functions must have a known
167 * size (used by x86_magic_trampoline)
169 #define x86_call_virtual(inst,basereg,disp) \
171 *(inst)++ = (unsigned char)0xff; \
172 x86_address_byte ((inst), 2, 2, (basereg)); \
173 x86_imm_emit32 ((inst), (disp)); \
176 /* emit an exception if condition is fail */
177 #define EMIT_COND_SYSTEM_EXCEPTION(cond,signed,exc_name) \
180 x86_branch8 (s->code, cond, 10, signed); \
181 x86_push_imm (s->code, exc_name); \
182 t = arch_get_throw_exception_by_name (); \
183 mono_add_jump_info (s, s->code, \
184 MONO_JUMP_INFO_ABS, t); \
185 x86_call_code (s->code, 0); \
188 /* we use this macro to move one lreg to another - source and
189 destination may overlap, but the register allocator has to
190 make sure that ((d1 < d2) && (s1 < s2))
192 #define MOVE_LREG(d1,d2,s1,s2) \
194 g_assert ((d1 < d2) && (s1 < s2)); \
195 if ((d1) <= (s1)) { \
197 x86_mov_reg_reg (s->code, d1, s1, 4); \
199 x86_mov_reg_reg (s->code, d2, s2, 4); \
202 x86_mov_reg_reg (s->code, d2, s2, 4); \
204 x86_mov_reg_reg (s->code, d1, s1, 4); \
212 # terminal definitions
216 %term CONST_I4 CONST_I8 CONST_R4 CONST_R8
217 %term LDIND_I1 LDIND_U1 LDIND_I2 LDIND_U2 LDIND_I4 LDIND_I8 LDIND_R4 LDIND_R8 LDIND_OBJ
218 %term STIND_I1 STIND_I2 STIND_I4 STIND_I8 STIND_R4 STIND_R8 STIND_OBJ
219 %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
220 %term BREAK SWITCH BR RET_VOID RET RET_OBJ ENDFINALLY
221 %term ADD ADD_OVF ADD_OVF_UN SUB SUB_OVF SUB_OVF_UN MUL MUL_OVF MUL_OVF_UN
222 %term DIV DIV_UN REM REM_UN AND OR XOR SHL SHR SHR_UN NEG NOT
223 %term COMPARE CBRANCH BRTRUE BRFALSE CSET
224 %term CONV_I4 CONV_I1 CONV_I2 CONV_I8 CONV_U1 CONV_U2 CONV_U4 CONV_U8 CONV_R4 CONV_R8 CONV_R_UN
225 %term INTF_ADDR VFUNC_ADDR NOP NEWARR NEWARR_SPEC NEWOBJ NEWOBJ_SPEC NEWSTRUCT CPOBJ POP INITOBJ
226 %term ISINST CASTCLASS UNBOX
227 %term CONV_OVF_I1 CONV_OVF_U1 CONV_OVF_I2 CONV_OVF_U2 CONV_OVF_U4 CONV_OVF_U8 CONV_OVF_I4
228 %term CONV_OVF_I4_UN CONV_OVF_U1_UN CONV_OVF_U2_UN
229 %term CONV_OVF_I2_UN CONV_OVF_I8_UN CONV_OVF_I1_UN
230 %term EXCEPTION THROW RETHROW HANDLER CHECKTHIS
231 %term LDLEN LDELEMA LDFTN LDVIRTFTN LDSTR LDSFLDA
232 %term REMOTE_LDFLDA REMOTE_STIND_I1 REMOTE_STIND_I2 REMOTE_STIND_I4
233 %term REMOTE_STIND_I8 REMOTE_STIND_R4 REMOTE_STIND_R8 REMOTE_STIND_OBJ
243 # integer constant folding
244 coni4: AND (coni4, coni4) {
245 tree->data.i = tree->left->data.i & tree->right->data.i;
248 coni4: OR (coni4, coni4) {
249 tree->data.i = tree->left->data.i | tree->right->data.i;
252 coni4: XOR (coni4, coni4) {
253 tree->data.i = tree->left->data.i ^ tree->right->data.i;
256 coni4: SHL (coni4, coni4) {
257 tree->data.i = tree->left->data.i << tree->right->data.i;
260 coni4: SHR (coni4, coni4) {
261 tree->data.i = tree->left->data.i >> tree->right->data.i;
265 tree->data.i = ~tree->left->data.i;
268 coni4: ADD (coni4, coni4) {
269 tree->data.i = tree->left->data.i + tree->right->data.i;
272 coni4: SUB (coni4, coni4) {
273 tree->data.i = tree->left->data.i - tree->right->data.i;
276 coni4: MUL (coni4, coni4) {
277 tree->data.i = tree->left->data.i * tree->right->data.i;
280 coni4: DIV (coni4, coni4) {
281 tree->data.i = tree->left->data.i / tree->right->data.i;
283 MBCOND (tree->right->data.i)
287 coni4: REM (coni4, coni4) {
288 tree->data.i = tree->left->data.i % tree->right->data.i;
290 MBCOND (tree->right->data.i)
303 tree->data.ainfo.offset = tree->data.i;
304 tree->data.ainfo.amode = AMImmediate;
308 tree->data.ainfo.offset = tree->data.i;
309 tree->data.ainfo.amode = AMImmediate;
312 acon: ADD (ADDR_G, coni4) {
313 tree->data.ainfo.offset = (unsigned)tree->left->data.p + tree->right->data.i;
314 tree->data.ainfo.amode = AMImmediate;
320 tree->data.ainfo.offset = 0;
321 tree->data.ainfo.basereg = tree->reg1;
322 tree->data.ainfo.amode = AMBase;
325 base: ADD (reg, coni4) {
326 tree->data.ainfo.offset = tree->right->data.i;
327 tree->data.ainfo.basereg = tree->left->reg1;
328 tree->data.ainfo.amode = AMBase;
332 tree->data.ainfo.offset = VARINFO (s, tree->data.i).offset;
333 tree->data.ainfo.basereg = X86_EBP;
334 tree->data.ainfo.amode = AMBase;
336 MBCOND (VARINFO (data, tree->data.i).reg < 0);
341 tree->data.ainfo.offset = 0;
342 tree->data.ainfo.indexreg = tree->reg1;
343 tree->data.ainfo.shift = 0;
344 tree->data.ainfo.amode = AMIndex;
347 index: SHL (reg, coni4) {
348 tree->data.ainfo.offset = 0;
349 tree->data.ainfo.amode = AMIndex;
350 tree->data.ainfo.indexreg = tree->left->reg1;
351 tree->data.ainfo.shift = tree->right->data.i;
353 MBCOND (tree->right->data.i == 0 ||
354 tree->right->data.i == 1 ||
355 tree->right->data.i == 2 ||
356 tree->right->data.i == 3);
361 index: MUL (reg, coni4) {
362 static int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
364 tree->data.ainfo.offset = 0;
365 tree->data.ainfo.amode = AMIndex;
366 tree->data.ainfo.indexreg = tree->left->reg1;
367 tree->data.ainfo.shift = fast_log2 [tree->right->data.i];
369 MBCOND (tree->right->data.i == 1 ||
370 tree->right->data.i == 2 ||
371 tree->right->data.i == 4 ||
372 tree->right->data.i == 8);
381 addr: ADD (index, base) {
382 tree->data.ainfo.offset = tree->right->data.ainfo.offset;
383 tree->data.ainfo.basereg = tree->right->data.ainfo.basereg;
384 tree->data.ainfo.amode = tree->left->data.ainfo.amode |
385 tree->right->data.ainfo.amode;
386 tree->data.ainfo.shift = tree->left->data.ainfo.shift;
387 tree->data.ainfo.indexreg = tree->left->data.ainfo.indexreg;
390 # we pass exception in ECX to catch handler
392 int offset = VARINFO (s, tree->data.i).offset;
393 int reg = VARINFO (s, tree->data.i).reg;
395 if (tree->reg1 != X86_ECX)
396 x86_mov_reg_reg (s->code, tree->reg1, X86_ECX, 4);
398 /* store it so that we can RETHROW it later */
400 x86_mov_membase_reg (s->code, X86_EBP, offset, tree->reg1, 4);
402 x86_mov_reg_reg (s->code, reg, tree->reg1, 4);
408 x86_push_reg (s->code, tree->left->reg1);
409 target = arch_get_throw_exception ();
410 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, target);
411 x86_call_code (s->code, target);
415 int off = VARINFO (s, tree->data.i).offset;
416 int reg = VARINFO (s, tree->data.i).reg;
420 x86_push_membase (s->code, X86_EBP, off);
422 x86_push_reg (s->code, reg);
424 target = arch_get_throw_exception ();
425 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, target);
426 x86_call_code (s->code, target);
430 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bb);
431 x86_call_imm (s->code, 0);
438 stmt: STIND_I4 (ADDR_L, ADD (LDIND_I4 (ADDR_L), CONST_I4)) {
439 int vn = tree->left->data.i;
440 int treg = VARINFO (s, vn).reg;
441 int offset = VARINFO (s, vn).offset;
442 int data = tree->right->right->data.i;
446 x86_inc_reg (s->code, treg);
448 x86_inc_membase (s->code, X86_EBP, offset);
451 x86_alu_reg_imm (s->code, X86_ADD, treg, data);
453 x86_alu_membase_imm (s->code, X86_ADD, X86_EBP, offset, data);
456 MBCOND (tree->right->left->left->data.i == tree->left->data.i);
460 stmt: STIND_I4 (ADDR_L, SUB (LDIND_I4 (ADDR_L), CONST_I4)) {
461 int vn = tree->left->data.i;
462 int treg = VARINFO (s, vn).reg;
463 int offset = VARINFO (s, vn).offset;
464 int data = tree->right->right->data.i;
468 x86_dec_reg (s->code, treg);
470 x86_dec_membase (s->code, X86_EBP, offset);
473 x86_alu_reg_imm (s->code, X86_SUB, treg, data);
475 x86_alu_membase_imm (s->code, X86_SUB, X86_EBP, offset, data);
478 MBCOND (tree->right->left->left->data.i == tree->left->data.i);
482 stmt: STIND_I4 (ADDR_L, ADD (LDIND_I4 (ADDR_L), reg)) {
483 int vn = tree->left->data.i;
484 int treg = VARINFO (s, vn).reg;
485 int sreg = tree->right->right->reg1;
486 int offset = VARINFO (s, vn).offset;
489 x86_alu_reg_reg (s->code, X86_ADD, treg, sreg);
491 x86_alu_membase_reg (s->code, X86_ADD, X86_EBP, offset, sreg);
494 MBCOND (tree->right->left->left->data.i == tree->left->data.i);
498 stmt: STIND_I4 (ADDR_L, LDIND_I4 (ADDR_L)) {
499 int treg1 = VARINFO (s, tree->left->data.i).reg;
500 int treg2 = VARINFO (s, tree->right->left->data.i).reg;
501 int offset1 = VARINFO (s, tree->left->data.i).offset;
502 int offset2 = VARINFO (s, tree->right->left->data.i).offset;
504 //{static int cx= 0; printf ("CX %5d\n", cx++);}
506 if (treg1 >= 0 && treg2 >= 0) {
507 x86_mov_reg_reg (s->code, treg1, treg2, 4);
510 if (treg1 >= 0 && treg2 < 0) {
511 x86_mov_reg_membase (s->code, treg1, X86_EBP, offset2, 4);
514 if (treg1 < 0 && treg2 >= 0) {
515 x86_mov_membase_reg (s->code, X86_EBP, offset1, treg2, 4);
519 g_assert_not_reached ();
522 MBCOND (VARINFO (data, tree->left->data.i).reg >= 0 ||
523 VARINFO (data, tree->right->left->data.i).reg >= 0);
527 stmt: STIND_I4 (addr, coni4) {
528 switch (tree->left->data.ainfo.amode) {
531 x86_mov_mem_imm (s->code, tree->left->data.ainfo.offset, tree->right->data.i, 4);
535 x86_mov_membase_imm (s->code, tree->left->data.ainfo.basereg,
536 tree->left->data.ainfo.offset, tree->right->data.i, 4);
539 x86_mov_memindex_imm (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
540 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
541 tree->right->data.i, 4);
544 x86_mov_memindex_imm (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
545 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
546 tree->right->data.i, 4);
551 stmt: STIND_I4 (addr, reg) {
553 switch (tree->left->data.ainfo.amode) {
556 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
560 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
561 tree->left->data.ainfo.offset, tree->right->reg1, 4);
564 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
565 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
566 tree->right->reg1, 4);
569 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
570 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
571 tree->right->reg1, 4);
576 stmt: REMOTE_STIND_I4 (reg, reg) {
579 int lreg = tree->left->reg1;
580 int rreg = tree->right->reg1;
589 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
590 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
591 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
593 /* this is a transparent proxy - remote the call */
595 /* save value to stack */
596 x86_push_reg (s->code, rreg);
598 x86_push_reg (s->code, X86_ESP);
599 x86_push_imm (s->code, tree->data.fi.field);
600 x86_push_imm (s->code, tree->data.fi.klass);
601 x86_push_reg (s->code, lreg);
602 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
603 x86_call_code (s->code, 0);
604 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
606 br [1] = s->code; x86_jump8 (s->code, 0);
608 x86_patch (br [0], s->code);
609 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
610 tree->data.fi.field->offset;
611 x86_mov_membase_reg (s->code, lreg, offset, rreg, 4);
613 x86_patch (br [1], s->code);
616 stmt: STIND_I1 (addr, reg) {
617 PRINT_REG ("STIND_I1", tree->right->reg1);
619 switch (tree->left->data.ainfo.amode) {
622 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 1);
626 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
627 tree->left->data.ainfo.offset, tree->right->reg1, 1);
630 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
631 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
632 tree->right->reg1, 1);
635 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
636 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
637 tree->right->reg1, 1);
642 stmt: REMOTE_STIND_I1 (reg, reg) {
645 int lreg = tree->left->reg1;
646 int rreg = tree->right->reg1;
655 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
656 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
657 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
659 /* this is a transparent proxy - remote the call */
661 /* save value to stack */
662 x86_push_reg (s->code, rreg);
664 x86_push_reg (s->code, X86_ESP);
665 x86_push_imm (s->code, tree->data.fi.field);
666 x86_push_imm (s->code, tree->data.fi.klass);
667 x86_push_reg (s->code, lreg);
668 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
669 x86_call_code (s->code, 0);
670 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
672 br [1] = s->code; x86_jump8 (s->code, 0);
674 x86_patch (br [0], s->code);
675 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
676 tree->data.fi.field->offset;
677 x86_mov_membase_reg (s->code, lreg, offset, rreg, 1);
679 x86_patch (br [1], s->code);
682 stmt: STIND_I2 (addr, reg) {
683 PRINT_REG ("STIND_I2", tree->right->reg1);
685 switch (tree->left->data.ainfo.amode) {
688 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 2);
692 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
693 tree->left->data.ainfo.offset, tree->right->reg1, 2);
696 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
697 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
698 tree->right->reg1, 2);
701 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
702 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
703 tree->right->reg1, 2);
708 stmt: REMOTE_STIND_I2 (reg, reg) {
711 int lreg = tree->left->reg1;
712 int rreg = tree->right->reg1;
721 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
722 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
723 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
725 /* this is a transparent proxy - remote the call */
727 /* save value to stack */
728 x86_push_reg (s->code, rreg);
730 x86_push_reg (s->code, X86_ESP);
731 x86_push_imm (s->code, tree->data.fi.field);
732 x86_push_imm (s->code, tree->data.fi.klass);
733 x86_push_reg (s->code, lreg);
734 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
735 x86_call_code (s->code, 0);
736 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
738 br [1] = s->code; x86_jump8 (s->code, 0);
740 x86_patch (br [0], s->code);
741 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
742 tree->data.fi.field->offset;
743 x86_mov_membase_reg (s->code, lreg, offset, rreg, 2);
745 x86_patch (br [1], s->code);
748 reg: LDIND_I4 (ADDR_L) {
749 int treg = VARINFO (s, tree->left->data.i).reg;
751 if (treg != tree->reg1)
752 x86_mov_reg_reg (s->code, tree->reg1, treg, 4);
755 MBCOND ((VARINFO (data, tree->left->data.i).reg >= 0));
759 stmt: STIND_I4 (ADDR_L, coni4) {
760 int treg = VARINFO (s, tree->left->data.i).reg;
762 x86_mov_reg_imm (s->code, treg, tree->right->data.i);
765 MBCOND ((VARINFO (data, tree->left->data.i).reg >= 0));
769 stmt: STIND_I4 (ADDR_L, LDIND_I4 (ADDR_L)) {
770 int treg = VARINFO (s, tree->left->data.i).reg;
771 int offset = VARINFO (s, tree->right->left->data.i).offset;
773 x86_mov_reg_membase (s->code, treg, X86_EBP, offset, 4);
775 MBCOND ((VARINFO (data, tree->left->data.i).reg >= 0));
776 MBCOND ((VARINFO (data, tree->right->left->data.i).reg < 0));
780 stmt: STIND_I4 (ADDR_L, reg) {
781 int treg = VARINFO (s, tree->left->data.i).reg;
783 if (treg != tree->right->reg1)
784 x86_mov_reg_reg (s->code, treg, tree->right->reg1, 4);
787 MBCOND ((VARINFO (data, tree->left->data.i).reg >= 0));
792 reg: LDIND_I4 (addr) {
794 switch (tree->left->data.ainfo.amode) {
797 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
801 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
802 tree->left->data.ainfo.offset, 4);
805 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
806 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
809 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
810 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
811 tree->left->data.ainfo.shift, 4);
816 PRINT_REG ("LDIND_I4", tree->reg1);
819 reg: LDIND_I1 (addr) {
820 switch (tree->left->data.ainfo.amode) {
823 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, FALSE);
827 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
828 tree->left->data.ainfo.offset, TRUE, FALSE);
831 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
832 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, TRUE, FALSE);
835 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
836 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
837 tree->left->data.ainfo.shift, TRUE, FALSE);
841 PRINT_REG ("LDIND_I1", tree->reg1);
844 reg: LDIND_U1 (addr) {
845 switch (tree->left->data.ainfo.amode) {
848 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, FALSE);
852 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
853 tree->left->data.ainfo.offset, FALSE, FALSE);
856 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
857 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, FALSE, FALSE);
860 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
861 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
862 tree->left->data.ainfo.shift, FALSE, FALSE);
866 PRINT_REG ("LDIND_U1", tree->reg1);
869 reg: LDIND_I2 (addr) {
870 switch (tree->left->data.ainfo.amode) {
873 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, TRUE);
877 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
878 tree->left->data.ainfo.offset, TRUE, TRUE);
881 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
882 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, TRUE, TRUE);
885 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
886 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
887 tree->left->data.ainfo.shift, TRUE, TRUE);
891 PRINT_REG ("LDIND_U2", tree->reg1);
894 reg: LDIND_U2 (addr) {
895 switch (tree->left->data.ainfo.amode) {
898 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, TRUE);
902 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
903 tree->left->data.ainfo.offset, FALSE, TRUE);
906 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
907 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, FALSE, TRUE);
910 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
911 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
912 tree->left->data.ainfo.shift, FALSE, TRUE);
916 PRINT_REG ("LDIND_U2", tree->reg1);
919 reg: REMOTE_LDFLDA (reg) {
922 int lreg = tree->left->reg1;
927 if (tree->reg1 != treg)
928 x86_push_reg (s->code, treg);
930 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
931 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
932 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
934 /* this is a transparent proxy - remote the call */
936 x86_push_reg (s->code, X86_EAX);
938 x86_push_reg (s->code, X86_EDX);
939 x86_push_reg (s->code, X86_ECX);
941 x86_push_reg (s->code, X86_ESP);
942 x86_push_imm (s->code, tree->data.fi.field);
943 x86_push_imm (s->code, tree->data.fi.klass);
944 x86_push_reg (s->code, lreg);
945 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_load_remote_field);
946 x86_call_code (s->code, 0);
947 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
950 x86_mov_reg_reg (s->code, treg, X86_EAX, 4);
952 x86_pop_reg (s->code, X86_ECX);
954 x86_pop_reg (s->code, X86_EDX);
956 x86_pop_reg (s->code, X86_EAX);
958 x86_mov_reg_reg (s->code, tree->reg1, treg, 4);
960 br [1] = s->code; x86_jump8 (s->code, 0);
962 x86_patch (br [0], s->code);
963 if (tree->data.fi.klass->valuetype)
964 x86_lea_membase (s->code, tree->reg1, lreg,
965 tree->data.fi.field->offset - sizeof (MonoObject));
967 x86_lea_membase (s->code, tree->reg1, lreg, tree->data.fi.field->offset);
969 x86_patch (br [1], s->code);
971 if (tree->reg1 != treg)
972 x86_pop_reg (s->code, treg);
976 int offset = VARINFO (s, tree->data.i).offset;
978 x86_lea_membase (s->code, tree->reg1, X86_EBP, offset);
980 PRINT_REG ("ADDR_L", tree->reg1);
982 MBCOND (VARINFO (data, tree->data.i).reg < 0);
988 x86_mov_reg_imm (s->code, tree->reg1, tree->data.p);
992 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
996 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
1000 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
1003 reg: CONV_U2 (reg) {
1004 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
1007 # warning: this chain rule requires a register
1009 x86_mov_reg_imm (s->code, tree->reg1, tree->data.i);
1012 reg: CONV_I4 (reg) {
1013 if (tree->reg1 != tree->left->reg1)
1014 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1015 PRINT_REG ("CONV_I4", tree->left->reg1);
1018 reg: CONV_U4 (reg) {
1019 if (tree->reg1 != tree->left->reg1)
1020 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1021 PRINT_REG ("CONV_U4", tree->left->reg1);
1024 reg: CONV_OVF_I4 (reg) {
1025 if (tree->reg1 != tree->left->reg1)
1026 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1027 PRINT_REG ("CONV_OVF_I4", tree->left->reg1);
1030 reg: CONV_OVF_U4 (reg) {
1031 /* Keep in sync with CONV_OVF_I4_UN below, they are the same on 32-bit machines */
1032 x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
1033 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1034 if (tree->reg1 != tree->left->reg1)
1035 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1038 reg: CONV_OVF_I4_UN (reg) {
1039 /* Keep in sync with CONV_OVF_U4 above, they are the same on 32-bit machines */
1040 x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
1041 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1042 if (tree->reg1 != tree->left->reg1)
1043 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1046 reg: CONV_OVF_I1 (reg) {
1047 /* probe value to be within -128 to 127 */
1048 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 127);
1049 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, TRUE, "OverflowException");
1050 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, -128);
1051 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GT, TRUE, "OverflowException");
1052 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
1055 reg: CONV_OVF_I1_UN (reg) {
1056 /* probe values between 0 to 128 */
1057 x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff80);
1058 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1059 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
1062 reg: CONV_OVF_U1 (reg) {
1063 /* Keep in sync with CONV_OVF_U1_UN routine below, they are the same on 32-bit machines */
1064 /* probe value to be within 0 to 255 */
1065 x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff00);
1066 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1067 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
1070 reg: CONV_OVF_U1_UN (reg) {
1071 /* Keep in sync with CONV_OVF_U1 routine above, they are the same on 32-bit machines */
1072 /* probe value to be within 0 to 255 */
1073 x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff00);
1074 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1075 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
1078 reg: CONV_OVF_I2 (reg) {
1079 /* Probe value to be within -32768 and 32767 */
1080 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 32767);
1081 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, TRUE, "OverflowException");
1082 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, -32768);
1083 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GE, TRUE, "OverflowException");
1084 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
1087 reg: CONV_OVF_U2 (reg) {
1088 /* Keep in sync with CONV_OVF_U2_UN below, they are the same on 32-bit machines */
1089 /* Probe value to be within 0 and 65535 */
1090 x86_test_reg_imm (s->code, tree->left->reg1, 0xffff0000);
1091 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
1092 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
1095 reg: CONV_OVF_U2_UN (reg) {
1096 /* Keep in sync with CONV_OVF_U2 above, they are the same on 32-bit machines */
1097 /* Probe value to be within 0 and 65535 */
1098 x86_test_reg_imm (s->code, tree->left->reg1, 0xffff0000);
1099 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1100 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
1103 reg: CONV_OVF_I2_UN (reg) {
1104 /* Convert uint value into short, value within 0 and 32767 */
1105 x86_test_reg_imm (s->code, tree->left->reg1, 0xffff8000);
1106 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1107 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
1110 reg: MUL (reg, coni4) "MB_USE_OPT1(0)" {
1111 unsigned int i, j, k, v;
1113 v = tree->right->data.i;
1114 for (i = 0, j = 1, k = 0xfffffffe; i < 32; i++, j = j << 1, k = k << 1) {
1119 if (v < 0 || i == 32 || v & k) {
1122 /* LEA r1, [r2 + r2*2] */
1123 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 1);
1126 /* LEA r1, [r2 + r2*4] */
1127 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 2);
1130 /* LEA r1, [r2 + r2*2] */
1132 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 1);
1133 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->reg1);
1136 /* LEA r1, [r2 + r2*8] */
1137 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 3);
1140 /* LEA r1, [r2 + r2*4] */
1142 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 2);
1143 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->reg1);
1146 /* LEA r1, [r2 + r2*2] */
1148 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 1);
1149 x86_shift_reg_imm (s->code, X86_SHL, tree->reg1, 2);
1152 /* LEA r1, [r2 + r2*4] */
1153 /* LEA r1, [r1 + r1*4] */
1154 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 2);
1155 x86_lea_memindex (s->code, tree->reg1, tree->reg1, 0, tree->reg1, 2);
1158 /* LEA r1, [r2 + r2*4] */
1160 /* LEA r1, [r1 + r1*4] */
1161 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 2);
1162 x86_shift_reg_imm (s->code, X86_SHL, tree->reg1, 2);
1163 x86_lea_memindex (s->code, tree->reg1, tree->reg1, 0, tree->reg1, 2);
1166 x86_imul_reg_reg_imm (s->code, tree->reg1, tree->left->reg1, tree->right->data.i);
1170 x86_shift_reg_imm (s->code, X86_SHL, tree->left->reg1, i);
1171 if (tree->reg1 != tree->left->reg1)
1172 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1176 reg: MUL (reg, reg) {
1177 x86_imul_reg_reg (s->code, tree->left->reg1, tree->right->reg1);
1179 if (tree->reg1 != tree->left->reg1)
1180 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1183 reg: MUL_OVF (reg, reg) {
1184 x86_imul_reg_reg (s->code, tree->left->reg1, tree->right->reg1);
1185 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
1187 if (tree->reg1 != tree->left->reg1)
1188 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1191 reg: MUL_OVF_UN (reg, reg) {
1192 mono_assert (tree->right->reg1 != X86_EAX);
1194 if (tree->left->reg1 != X86_EAX)
1195 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1197 x86_mul_reg (s->code, tree->right->reg1, FALSE);
1198 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
1200 mono_assert (tree->reg1 == X86_EAX &&
1201 tree->reg2 == X86_EDX);
1204 reg: DIV (reg, coni4) {
1205 unsigned int i, j, k, v;
1207 v = tree->right->data.i;
1208 for (i = 0, j = 1, k = 0xfffffffe; i < 32; i++, j = j << 1, k = k << 1) {
1213 x86_shift_reg_imm (s->code, X86_SAR, tree->left->reg1, i);
1214 if (tree->reg1 != tree->left->reg1)
1215 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1218 unsigned int i, j, k, v;
1223 v = tree->right->data.i;
1224 for (i = 0, j = 1, k = 0xfffffffe; i < 32; i++, j = j << 1, k = k << 1) {
1229 if (i == 32 || v & k)
1236 reg: DIV (reg, reg) {
1237 mono_assert (tree->right->reg1 != X86_EAX);
1239 if (tree->left->reg1 != X86_EAX)
1240 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1243 x86_div_reg (s->code, tree->right->reg1, TRUE);
1245 mono_assert (tree->reg1 == X86_EAX &&
1246 tree->reg2 == X86_EDX);
1249 reg: DIV_UN (reg, coni4) {
1250 unsigned int i, j, k, v;
1253 v = tree->right->data.i;
1254 for (i = 0, j = 1, k = 0xfffffffe; i < 32; i++, j = j << 1, k = k << 1) {
1259 if (i == 32 || v & k) {
1260 for (i = 32, j = 0x80000000; --i >= 0; j >>= 1) {
1264 /* k = 32 + number of significant bits in v - 1 */
1268 for (i = 0; i < k; i++) f *= 2.0f;
1274 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg1, k - 32);
1275 if (tree->reg1 != tree->left->reg1)
1276 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1277 } else if (r < 0.5f) {
1278 if (tree->left->reg1 != X86_EAX)
1279 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1280 x86_mov_reg_imm (s->code, X86_EDX, (guint32) floor(f));
1281 /* x86_inc_reg (s->code, X86_EAX); */
1282 /* INC is faster but we have to check for overflow. */
1283 x86_alu_reg_imm (s->code, X86_ADD, X86_EAX, 1);
1284 x86_branch8(s->code, X86_CC_C, 2, FALSE);
1285 x86_mul_reg (s->code, X86_EDX, FALSE);
1286 x86_shift_reg_imm (s->code, X86_SHR, X86_EDX, k - 32);
1287 if (tree->reg1 != X86_EDX)
1288 x86_mov_reg_reg (s->code, tree->reg1, X86_EDX, 4);
1290 if (tree->left->reg1 != X86_EAX)
1291 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1292 x86_mov_reg_imm (s->code, X86_EDX, (guint32) ceil(f));
1293 x86_mul_reg (s->code, X86_EDX, FALSE);
1294 x86_shift_reg_imm (s->code, X86_SHR, X86_EDX, k - 32);
1295 if (tree->reg1 != X86_EDX)
1296 x86_mov_reg_reg (s->code, tree->reg1, X86_EDX, 4);
1299 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg1, i);
1300 if (tree->reg1 != tree->left->reg1)
1301 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1306 reg: DIV_UN (reg, reg) {
1307 mono_assert (tree->right->reg1 != X86_EAX);
1309 if (tree->left->reg1 != X86_EAX)
1310 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1312 x86_mov_reg_imm (s->code, X86_EDX, 0);
1313 x86_div_reg (s->code, tree->right->reg1, FALSE);
1315 mono_assert (tree->reg1 == X86_EAX &&
1316 tree->reg2 == X86_EDX);
1319 reg: REM (reg, reg) {
1320 mono_assert (tree->right->reg1 != X86_EAX);
1321 mono_assert (tree->right->reg1 != X86_EDX);
1323 if (tree->left->reg1 != X86_EAX)
1324 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1326 /* sign extend to 64bit in EAX/EDX */
1328 x86_div_reg (s->code, tree->right->reg1, TRUE);
1329 x86_mov_reg_reg (s->code, X86_EAX, X86_EDX, 4);
1331 mono_assert (tree->reg1 == X86_EAX &&
1332 tree->reg2 == X86_EDX);
1335 reg: REM_UN (reg, reg) {
1336 mono_assert (tree->right->reg1 != X86_EAX);
1337 mono_assert (tree->right->reg1 != X86_EDX);
1339 if (tree->left->reg1 != X86_EAX)
1340 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1342 /* zero extend to 64bit in EAX/EDX */
1343 x86_mov_reg_imm (s->code, X86_EDX, 0);
1344 x86_div_reg (s->code, tree->right->reg1, FALSE);
1345 x86_mov_reg_reg (s->code, X86_EAX, X86_EDX, 4);
1347 mono_assert (tree->reg1 == X86_EAX &&
1348 tree->reg2 == X86_EDX);
1351 reg: ADD (reg, coni4) "MB_USE_OPT1(0)" {
1352 if (tree->right->data.i == 1)
1353 x86_inc_reg (s->code, tree->left->reg1);
1355 x86_alu_reg_imm (s->code, X86_ADD, tree->left->reg1, tree->right->data.i);
1357 if (tree->reg1 != tree->left->reg1)
1358 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1362 reg: ADD (reg, LDIND_I4 (ADDR_L)) {
1363 int treg = VARINFO (s, tree->right->left->data.i).reg;
1365 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, treg);
1367 if (tree->reg1 != tree->left->reg1)
1368 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1370 MBCOND ((VARINFO (data, tree->right->left->data.i).reg >= 0));
1374 reg: ADD (reg, reg) {
1375 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
1377 if (tree->reg1 != tree->left->reg1)
1378 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1381 reg: ADD_OVF (reg, reg) {
1382 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
1383 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
1385 if (tree->reg1 != tree->left->reg1)
1386 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1389 reg: ADD_OVF_UN (reg, reg) {
1390 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
1391 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
1393 if (tree->reg1 != tree->left->reg1)
1394 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1397 reg: SUB (reg, coni4) "MB_USE_OPT1(0)" {
1398 if (tree->right->data.i == 1)
1399 x86_dec_reg (s->code, tree->left->reg1);
1401 x86_alu_reg_imm (s->code, X86_SUB, tree->left->reg1, tree->right->data.i);
1403 if (tree->reg1 != tree->left->reg1)
1404 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1407 reg: SUB (reg, LDIND_I4 (ADDR_L)) {
1408 int treg = VARINFO (s, tree->right->left->data.i).reg;
1410 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, treg);
1412 if (tree->reg1 != tree->left->reg1)
1413 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1415 MBCOND ((VARINFO (data, tree->right->left->data.i).reg >= 0));
1419 reg: SUB (reg, reg) {
1420 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
1422 if (tree->reg1 != tree->left->reg1)
1423 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1426 reg: SUB_OVF (reg, reg) {
1427 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
1428 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
1430 if (tree->reg1 != tree->left->reg1)
1431 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1434 reg: SUB_OVF_UN (reg, reg) {
1435 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
1436 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
1438 if (tree->reg1 != tree->left->reg1)
1439 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1442 reg: CSET (cflags) {
1444 switch (tree->data.i) {
1446 x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
1449 x86_set_reg (s->code, X86_CC_GT, tree->reg1, TRUE);
1452 x86_set_reg (s->code, X86_CC_GT, tree->reg1, FALSE);
1455 x86_set_reg (s->code, X86_CC_LT, tree->reg1, TRUE);
1458 x86_set_reg (s->code, X86_CC_LT, tree->reg1, FALSE);
1461 g_assert_not_reached ();
1464 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
1467 reg: AND (reg, coni4) "MB_USE_OPT1(0)" {
1468 x86_alu_reg_imm (s->code, X86_AND, tree->left->reg1, tree->right->data.i);
1470 if (tree->reg1 != tree->left->reg1)
1471 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1474 reg: AND (reg, reg) {
1475 x86_alu_reg_reg (s->code, X86_AND, tree->left->reg1, tree->right->reg1);
1477 if (tree->reg1 != tree->left->reg1)
1478 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1481 reg: OR (reg, coni4) "MB_USE_OPT1(0)" {
1482 x86_alu_reg_imm (s->code, X86_OR, tree->left->reg1, tree->right->data.i);
1484 if (tree->reg1 != tree->left->reg1)
1485 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1488 reg: OR (reg, reg) {
1489 x86_alu_reg_reg (s->code, X86_OR, tree->left->reg1, tree->right->reg1);
1491 if (tree->reg1 != tree->left->reg1)
1492 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1495 reg: XOR (reg, coni4) "MB_USE_OPT1(0)" {
1496 x86_alu_reg_imm (s->code, X86_XOR, tree->left->reg1, tree->right->data.i);
1498 if (tree->reg1 != tree->left->reg1)
1499 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1502 reg: XOR (reg, reg) {
1503 x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->right->reg1);
1505 if (tree->reg1 != tree->left->reg1)
1506 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1510 x86_neg_reg (s->code, tree->left->reg1);
1512 if (tree->reg1 != tree->left->reg1)
1513 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1517 x86_not_reg (s->code, tree->left->reg1);
1519 if (tree->reg1 != tree->left->reg1)
1520 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1523 reg: SHL (reg, coni4) {
1524 x86_shift_reg_imm (s->code, X86_SHL, tree->left->reg1, tree->right->data.i);
1526 if (tree->reg1 != tree->left->reg1)
1527 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1530 reg: SHL (reg, reg) {
1531 if (tree->right->reg1 != X86_ECX) {
1532 x86_push_reg (s->code, X86_ECX);
1533 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1535 x86_shift_reg (s->code, X86_SHL, tree->left->reg1);
1537 if (tree->reg1 != tree->left->reg1)
1538 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1540 if (tree->right->reg1 != X86_ECX)
1541 x86_pop_reg (s->code, X86_ECX);
1543 mono_assert (tree->reg1 != X86_ECX &&
1544 tree->left->reg1 != X86_ECX);
1547 reg: SHR (reg, coni4) {
1548 x86_shift_reg_imm (s->code, X86_SAR, tree->left->reg1, tree->right->data.i);
1550 if (tree->reg1 != tree->left->reg1)
1551 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1554 reg: SHR (reg, reg) {
1555 if (tree->right->reg1 != X86_ECX) {
1556 x86_push_reg (s->code, X86_ECX);
1557 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1560 x86_shift_reg (s->code, X86_SAR, tree->left->reg1);
1562 if (tree->reg1 != tree->left->reg1)
1563 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1565 if (tree->right->reg1 != X86_ECX)
1566 x86_pop_reg (s->code, X86_ECX);
1568 mono_assert (tree->reg1 != X86_ECX &&
1569 tree->left->reg1 != X86_ECX);
1572 reg: SHR_UN (reg, coni4) {
1573 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg1, tree->right->data.i);
1575 if (tree->reg1 != tree->left->reg1)
1576 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1579 reg: SHR_UN (reg, reg) {
1580 if (tree->right->reg1 != X86_ECX) {
1581 x86_push_reg (s->code, X86_ECX);
1582 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1585 x86_shift_reg (s->code, X86_SHR, tree->left->reg1);
1587 if (tree->reg1 != tree->left->reg1)
1588 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1590 if (tree->right->reg1 != X86_ECX)
1591 x86_pop_reg (s->code, X86_ECX);
1593 mono_assert (tree->reg1 != X86_ECX &&
1594 tree->left->reg1 != X86_ECX);
1597 reg: LDSFLDA (coni4) {
1598 if (tree->reg1 != X86_EAX)
1599 x86_push_reg (s->code, X86_EAX);
1600 x86_push_reg (s->code, X86_ECX);
1601 x86_push_reg (s->code, X86_EDX);
1603 x86_push_imm (s->code, tree->left->data.i);
1604 x86_push_imm (s->code, tree->data.klass);
1605 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_ldsflda);
1606 x86_call_code (s->code, 0);
1607 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1609 x86_pop_reg (s->code, X86_EDX);
1610 x86_pop_reg (s->code, X86_ECX);
1611 if (tree->reg1 != X86_EAX) {
1612 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1613 x86_pop_reg (s->code, X86_EAX);
1619 x86_mov_reg_membase (s->code, tree->reg1, tree->left->reg1,
1620 G_STRUCT_OFFSET (MonoArray, max_length), 4);
1623 reg: LDELEMA (reg, coni4) {
1626 x86_alu_membase_imm (s->code, X86_CMP, tree->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length), tree->right->data.i);
1627 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GT, FALSE, "IndexOutOfRangeException");
1629 ind = tree->data.i * tree->right->data.i + G_STRUCT_OFFSET (MonoArray, vector);
1631 x86_alu_reg_imm (s->code, X86_ADD, tree->left->reg1, ind);
1633 if (tree->reg1 != tree->left->reg1)
1634 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1638 reg: LDELEMA (reg, reg) {
1640 x86_alu_reg_membase (s->code, X86_CMP, tree->right->reg1, tree->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length));
1641 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LT, FALSE, "IndexOutOfRangeException");
1643 if (tree->data.i == 1 || tree->data.i == 2 ||
1644 tree->data.i == 4 || tree->data.i == 8) {
1645 static int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
1646 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1,
1647 G_STRUCT_OFFSET (MonoArray, vector), tree->right->reg1,
1648 fast_log2 [tree->data.i]);
1650 x86_imul_reg_reg_imm (s->code, tree->right->reg1, tree->right->reg1, tree->data.i);
1651 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
1652 x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, G_STRUCT_OFFSET (MonoArray, vector));
1657 if (tree->reg1 != X86_EAX)
1658 x86_push_reg (s->code, X86_EAX);
1659 x86_push_reg (s->code, X86_ECX);
1660 x86_push_reg (s->code, X86_EDX);
1662 x86_push_imm (s->code, tree->data.p);
1663 x86_push_imm (s->code, s->method->klass->image);
1664 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_ldstr_wrapper);
1665 x86_call_code (s->code, 0);
1666 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1668 x86_pop_reg (s->code, X86_EDX);
1669 x86_pop_reg (s->code, X86_ECX);
1670 if (tree->reg1 != X86_EAX) {
1671 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1672 x86_pop_reg (s->code, X86_EAX);
1675 PRINT_REG ("LDSTR", tree->reg1);
1679 if (tree->reg1 != X86_EAX)
1680 x86_push_reg (s->code, X86_EAX);
1681 x86_push_reg (s->code, X86_ECX);
1682 x86_push_reg (s->code, X86_EDX);
1684 x86_push_reg (s->code, tree->left->reg1);
1685 x86_push_imm (s->code, tree->data.p);
1686 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_array_new_wrapper);
1687 x86_call_code (s->code, 0);
1688 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer) + 4);
1690 x86_pop_reg (s->code, X86_EDX);
1691 x86_pop_reg (s->code, X86_ECX);
1692 if (tree->reg1 != X86_EAX) {
1693 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1694 x86_pop_reg (s->code, X86_EAX);
1697 PRINT_REG ("NEWARR", tree->reg1);
1700 reg: NEWARR_SPEC (reg) {
1701 if (tree->reg1 != X86_EAX)
1702 x86_push_reg (s->code, X86_EAX);
1703 x86_push_reg (s->code, X86_ECX);
1704 x86_push_reg (s->code, X86_EDX);
1706 x86_push_reg (s->code, tree->left->reg1);
1707 x86_push_imm (s->code, tree->data.p);
1708 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_array_new_specific);
1709 x86_call_code (s->code, 0);
1710 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer) + 4);
1712 x86_pop_reg (s->code, X86_EDX);
1713 x86_pop_reg (s->code, X86_ECX);
1714 if (tree->reg1 != X86_EAX) {
1715 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1716 x86_pop_reg (s->code, X86_EAX);
1719 PRINT_REG ("NEWARR_SPEC", tree->reg1);
1723 if (tree->reg1 != X86_EAX)
1724 x86_push_reg (s->code, X86_EAX);
1725 x86_push_reg (s->code, X86_ECX);
1726 x86_push_reg (s->code, X86_EDX);
1728 x86_push_imm (s->code, tree->data.klass);
1729 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_object_new_wrapper);
1730 x86_call_code (s->code, 0);
1731 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
1733 x86_pop_reg (s->code, X86_EDX);
1734 x86_pop_reg (s->code, X86_ECX);
1735 if (tree->reg1 != X86_EAX) {
1736 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1737 x86_pop_reg (s->code, X86_EAX);
1739 PRINT_REG ("NEWOBJ", tree->reg1);
1743 if (tree->reg1 != X86_EAX)
1744 x86_push_reg (s->code, X86_EAX);
1745 x86_push_reg (s->code, X86_ECX);
1746 x86_push_reg (s->code, X86_EDX);
1748 x86_push_imm (s->code, tree->data.p);
1749 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_object_new_specific);
1750 x86_call_code (s->code, 0);
1751 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
1753 x86_pop_reg (s->code, X86_EDX);
1754 x86_pop_reg (s->code, X86_ECX);
1755 if (tree->reg1 != X86_EAX) {
1756 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1757 x86_pop_reg (s->code, X86_EAX);
1759 PRINT_REG ("NEWOBJ_SPEC", tree->reg1);
1763 int size = tree->data.i;
1766 mono_assert (size > 0);
1771 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);
1772 x86_mov_reg_reg (s->code, tree->reg1, X86_ESP, 4);
1776 if (tree->reg1 != tree->left->reg1)
1777 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1779 x86_push_reg (s->code, tree->reg1);
1780 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, 0, 4);
1781 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, 0, 4);
1782 x86_alu_membase_imm (s->code, X86_CMP, tree->reg1,
1783 G_STRUCT_OFFSET (MonoClass, element_class), ((int)(tree->data.klass->element_class)));
1784 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "InvalidCastException");
1785 x86_pop_reg (s->code, tree->reg1);
1786 x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, sizeof (MonoObject));
1789 reg: CASTCLASS (reg) {
1790 MonoClass *klass = tree->data.klass;
1792 int lreg = tree->left->reg1;
1794 x86_push_reg (s->code, lreg);
1795 x86_test_reg_reg (s->code, lreg, lreg);
1796 br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
1798 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1799 /* lreg = obj->vtable */
1800 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1802 x86_alu_membase_imm (s->code, X86_CMP, lreg, G_STRUCT_OFFSET (MonoVTable, max_interface_id),
1803 klass->interface_id);
1804 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GE, FALSE, "InvalidCastException");
1805 /* lreg = obj->vtable->interface_offsets */
1806 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
1807 x86_alu_membase_imm (s->code, X86_CMP, lreg, klass->interface_id << 2, 0);
1808 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NE, FALSE, "InvalidCastException");
1811 /* lreg = obj->vtable */
1812 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1813 /* lreg = obj->vtable->klass */
1814 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1818 x86_alu_membase_imm (s->code, X86_CMP, lreg, G_STRUCT_OFFSET (MonoClass, rank), klass->rank);
1819 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "InvalidCastException");
1820 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, element_class), 4);
1821 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, baseval), 4);
1822 x86_alu_reg_mem (s->code, X86_SUB, lreg, &klass->element_class->baseval);
1823 x86_alu_reg_mem (s->code, X86_CMP, lreg, &klass->element_class->diffval);
1824 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, FALSE, "InvalidCastException");
1828 if (klass->marshalbyref) {
1829 /* check for transparent_proxy */
1830 x86_alu_reg_imm (s->code, X86_CMP, lreg, (int)mono_defaults.transparent_proxy_class);
1831 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
1834 x86_mov_reg_membase (s->code, lreg, X86_ESP, 0, 4);
1835 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoTransparentProxy,
1838 x86_patch (br [1], s->code);
1841 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, baseval), 4);
1842 x86_alu_reg_mem (s->code, X86_SUB, lreg, &klass->baseval);
1843 x86_alu_reg_mem (s->code, X86_CMP, lreg, &klass->diffval);
1844 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, FALSE, "InvalidCastException");
1848 x86_patch (br [0], s->code);
1849 x86_pop_reg (s->code, tree->reg1);
1853 MonoClass *klass = tree->data.klass;
1855 int lreg = tree->left->reg1;
1857 x86_push_reg (s->code, lreg);
1858 x86_test_reg_reg (s->code, lreg, lreg);
1859 br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
1861 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1862 /* lreg = obj->vtable */
1863 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1865 x86_alu_membase_imm (s->code, X86_CMP, lreg, G_STRUCT_OFFSET (MonoVTable, max_interface_id),
1866 klass->interface_id);
1867 br [1] = s->code; x86_branch8 (s->code, X86_CC_LT, 0, FALSE);
1868 /* lreg = obj->vtable->interface_offsets */
1869 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
1870 x86_alu_membase_imm (s->code, X86_CMP, lreg, klass->interface_id << 2, 0);
1871 br [2] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
1872 x86_patch (br [1], s->code);
1873 x86_mov_membase_imm (s->code, X86_ESP, 0, 0, 4);
1874 x86_patch (br [2], s->code);
1878 /* lreg = obj->vtable */
1879 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1880 /* lreg = obj->vtable->klass */
1881 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1885 x86_alu_membase_imm (s->code, X86_CMP, lreg, G_STRUCT_OFFSET (MonoClass, rank), klass->rank);
1886 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
1887 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, element_class), 4);
1888 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, baseval), 4);
1889 x86_alu_reg_mem (s->code, X86_SUB, lreg, &klass->element_class->baseval);
1890 x86_alu_reg_mem (s->code, X86_CMP, lreg, &klass->element_class->diffval);
1891 br [2] = s->code; x86_branch8 (s->code, X86_CC_LE, 0, FALSE);
1892 x86_patch (br [1], s->code);
1893 x86_mov_membase_imm (s->code, X86_ESP, 0, 0, 4);
1894 x86_patch (br [2], s->code);
1898 if (klass->marshalbyref) {
1899 /* check for transparent_proxy */
1900 x86_alu_reg_imm (s->code, X86_CMP, lreg, (int)mono_defaults.transparent_proxy_class);
1901 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
1904 x86_mov_reg_membase (s->code, lreg, X86_ESP, 0, 4);
1905 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoTransparentProxy,
1907 x86_patch (br [1], s->code);
1910 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, baseval), 4);
1911 x86_alu_reg_mem (s->code, X86_SUB, lreg, &klass->baseval);
1912 x86_alu_reg_mem (s->code, X86_CMP, lreg, &klass->diffval);
1913 br [2] = s->code; x86_branch8 (s->code, X86_CC_LE, 0, FALSE);
1914 x86_mov_membase_imm (s->code, X86_ESP, 0, 0, 4);
1915 x86_patch (br [2], s->code);
1919 x86_patch (br [0], s->code);
1920 x86_pop_reg (s->code, tree->reg1);
1923 stmt: INITOBJ (reg) {
1928 if (i == 1 || i == 2 || i == 4) {
1929 x86_mov_membase_imm (s->code, tree->left->reg1, 0, 0, i);
1933 i = tree->data.i / 4;
1934 j = tree->data.i % 4;
1936 x86_push_reg (s->code, X86_EAX);
1938 if (tree->left->reg1 != X86_EDI) {
1939 x86_push_reg (s->code, X86_EDI);
1940 x86_mov_reg_reg (s->code, X86_EDI, tree->left->reg1, 4);
1944 x86_push_reg (s->code, X86_ECX);
1945 x86_alu_reg_reg (s->code, X86_XOR, X86_EAX, X86_EAX);
1946 x86_mov_reg_imm (s->code, X86_ECX, i);
1948 x86_prefix (s->code, X86_REP_PREFIX);
1949 x86_stosl (s->code);
1950 x86_pop_reg (s->code, X86_ECX);
1952 for (i = 0; i < j; i++)
1953 x86_stosb (s->code);
1957 x86_mov_membase_imm (s->code, X86_EDI, 0, 0, 2);
1958 x86_mov_membase_imm (s->code, X86_EDI, 2, 0, 1);
1963 if (tree->left->reg1 != X86_EDI)
1964 x86_pop_reg (s->code, X86_EDI);
1966 x86_pop_reg (s->code, X86_EAX);
1974 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bb);
1975 x86_jump32 (s->code, 0);
1978 cflags: COMPARE (reg, LDIND_I4 (ADDR_L)) {
1979 int treg = VARINFO (s, tree->right->left->data.i).reg;
1980 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, treg);
1982 MBCOND ((VARINFO (data, tree->right->left->data.i).reg >= 0));
1986 cflags: COMPARE (LDIND_I4 (ADDR_L), coni4) {
1987 int treg = VARINFO (s, tree->left->left->data.i).reg;
1988 x86_alu_reg_imm (s->code, X86_CMP, treg, tree->right->data.i);
1990 MBCOND ((VARINFO (data, tree->left->left->data.i).reg >= 0));
1994 cflags: COMPARE (LDIND_I4 (ADDR_L), reg) {
1995 int treg = VARINFO (s, tree->left->left->data.i).reg;
1996 x86_alu_reg_reg (s->code, X86_CMP, treg, tree->right->reg1);
1998 MBCOND ((VARINFO (data, tree->left->left->data.i).reg >= 0));
2002 cflags: COMPARE (LDIND_I4 (ADDR_L), coni4) {
2003 int offset = VARINFO (s, tree->left->left->data.i).offset;
2004 x86_alu_membase_imm (s->code, X86_CMP, X86_EBP, offset, tree->right->data.i);
2006 MBCOND ((VARINFO (data, tree->left->left->data.i).reg < 0));
2010 cflags: COMPARE (reg, coni4) {
2011 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
2014 cflags: COMPARE (reg, reg) {
2015 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2019 stmt: CBRANCH (cflags) {
2020 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
2022 switch (tree->data.bi.cond) {
2024 x86_branch32 (s->code, X86_CC_LT, 0, TRUE);
2027 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
2030 x86_branch32 (s->code, X86_CC_GT, 0, TRUE);
2033 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
2036 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
2039 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
2042 x86_branch32 (s->code, X86_CC_GE, 0, TRUE);
2045 x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
2048 x86_branch32 (s->code, X86_CC_LE, 0, TRUE);
2051 x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
2054 g_assert_not_reached ();
2058 stmt: BRTRUE (LDIND_I4 (ADDR_L)) {
2059 int treg = VARINFO (s, tree->left->left->data.i).reg;
2060 int offset = VARINFO (s, tree->left->left->data.i).offset;
2063 x86_test_reg_reg (s->code, treg, treg);
2065 x86_alu_membase_imm (s->code, X86_CMP, X86_EBP, offset, 0);
2067 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bb);
2068 x86_branch32 (s->code, X86_CC_NE, 0, TRUE);
2071 stmt: BRTRUE (reg) {
2072 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
2073 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bb);
2074 x86_branch32 (s->code, X86_CC_NE, 0, TRUE);
2077 stmt: BRFALSE (LDIND_I4 (ADDR_L)) {
2078 int treg = VARINFO (s, tree->left->left->data.i).reg;
2079 int offset = VARINFO (s, tree->left->left->data.i).offset;
2082 x86_test_reg_reg (s->code, treg, treg);
2084 x86_alu_membase_imm (s->code, X86_CMP, X86_EBP, offset, 0);
2086 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bb);
2087 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
2089 //{static int cx= 0; printf ("CX1 %5d\n", cx++);}
2092 stmt: BRFALSE (reg) {
2093 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
2094 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bb);
2095 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
2099 x86_breakpoint (s->code);
2103 if (tree->left->reg1 != X86_EAX)
2104 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
2106 if (!tree->last_instr) {
2107 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_EPILOG, NULL);
2108 x86_jump32 (s->code, 0);
2113 if (!tree->last_instr) {
2114 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_EPILOG, NULL);
2115 x86_jump32 (s->code, 0);
2120 stmt: ARG_I4 (LDIND_I4 (addr)) {
2121 MBTree *at = tree->left->left;
2123 switch (at->data.ainfo.amode) {
2126 x86_push_mem (s->code, at->data.ainfo.offset);
2130 x86_push_membase (s->code, at->data.ainfo.basereg, at->data.ainfo.offset);
2133 x86_push_memindex (s->code, X86_NOBASEREG, at->data.ainfo.offset,
2134 at->data.ainfo.indexreg, at->data.ainfo.shift);
2137 x86_push_memindex (s->code, at->data.ainfo.basereg,
2138 at->data.ainfo.offset, at->data.ainfo.indexreg,
2139 at->data.ainfo.shift);
2144 stmt: ARG_I4 (LDIND_I4 (ADDR_L)) {
2145 int treg = VARINFO (s, tree->left->left->data.i).reg;
2146 x86_push_reg (s->code, treg);
2148 MBCOND ((VARINFO (data, tree->left->left->data.i).reg >= 0));
2152 stmt: ARG_I4 (reg) {
2153 x86_push_reg (s->code, tree->left->reg1);
2154 PRINT_REG ("ARG_I4", tree->left->reg1);
2157 # fixme: we must free the allocated strings somewhere
2158 stmt: ARG_STRING (reg) {
2159 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
2160 x86_push_reg (s->code, X86_EAX);
2161 x86_push_reg (s->code, X86_ECX);
2162 x86_push_reg (s->code, X86_EDX);
2164 x86_push_reg (s->code, tree->left->reg1);
2165 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_string_to_utf8);
2166 x86_call_code (s->code, 0);
2167 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
2169 x86_mov_membase_reg (s->code, X86_ESP, 12, X86_EAX, 4);
2171 x86_pop_reg (s->code, X86_EDX);
2172 x86_pop_reg (s->code, X86_ECX);
2173 x86_pop_reg (s->code, X86_EAX);
2176 stmt: ARG_I4 (ADDR_G) {
2177 x86_push_imm (s->code, tree->left->data.p);
2180 stmt: ARG_I4 (coni4) "MB_USE_OPT1(0)" {
2181 x86_push_imm (s->code, tree->left->data.i);
2185 PRINT_REG ("THIS", tree->reg1);
2188 reg: CHECKTHIS (reg) {
2189 /* try to access the vtable - this will raise an exception
2190 * if the object is NULL */
2191 x86_alu_membase_imm (s->code, X86_CMP, tree->left->reg1, 0, 0);
2192 if (tree->reg1 != tree->left->reg1)
2193 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2196 stmt: CHECKTHIS (reg) {
2197 x86_alu_membase_imm (s->code, X86_CMP, tree->left->reg1, 0, 0);
2202 reg: CALL_I4 (this, reg) {
2204 int lreg = tree->left->reg1;
2205 int rreg = tree->right->reg1;
2207 if (lreg == treg || rreg == treg)
2209 if (lreg == treg || rreg == treg)
2211 if (lreg == treg || rreg == treg)
2212 mono_assert_not_reached ();
2214 if (tree->left->op != MB_TERM_NOP) {
2215 mono_assert (lreg >= 0);
2216 x86_push_reg (s->code, lreg);
2219 if (tree->data.ci.vtype_num) {
2220 int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
2221 x86_lea_membase (s->code, treg, X86_EBP, offset);
2222 x86_push_reg (s->code, treg);
2225 x86_call_reg (s->code, rreg);
2227 if (tree->data.ci.args_size)
2228 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2230 PRINT_REG ("CALL_I4", tree->reg1);
2232 mono_assert (tree->reg1 == X86_EAX);
2235 reg: CALL_I4 (this, ADDR_G) {
2236 int lreg = tree->left->reg1;
2242 if (tree->left->op != MB_TERM_NOP) {
2243 mono_assert (lreg >= 0);
2244 x86_push_reg (s->code, lreg);
2245 x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
2248 if (tree->data.ci.vtype_num) {
2249 int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
2250 x86_lea_membase (s->code, treg, X86_EBP, offset);
2251 x86_push_reg (s->code, treg);
2254 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->right->data.p);
2255 x86_call_code (s->code, 0);
2257 if (tree->data.ci.args_size)
2258 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2260 PRINT_REG ("CALL_I4", tree->reg1);
2262 mono_assert (tree->reg1 == X86_EAX);
2265 reg: LDVIRTFTN (reg, INTF_ADDR) {
2266 int lreg = tree->left->reg1;
2268 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2269 x86_mov_reg_membase (s->code, lreg, lreg,
2270 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
2271 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
2272 x86_mov_reg_membase (s->code, tree->reg1, lreg, tree->right->data.m->slot << 2, 4);
2275 reg: CALL_I4 (this, INTF_ADDR) {
2276 int lreg = tree->left->reg1;
2282 if (tree->left->op != MB_TERM_NOP) {
2283 mono_assert (lreg >= 0);
2284 x86_push_reg (s->code, lreg);
2287 if (tree->data.ci.vtype_num) {
2288 int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
2289 x86_lea_membase (s->code, treg, X86_EBP, offset);
2290 x86_push_reg (s->code, treg);
2293 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2294 x86_mov_reg_membase (s->code, lreg, lreg,
2295 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
2296 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
2297 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
2299 if (tree->data.ci.args_size)
2300 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2302 PRINT_REG ("CALL_I4(INTERFACE)", tree->reg1);
2304 mono_assert (tree->reg1 == X86_EAX);
2307 reg: LDVIRTFTN (reg, VFUNC_ADDR) {
2308 int lreg = tree->left->reg1;
2310 x86_mov_reg_membase (s->code, tree->reg1, lreg, 0, 4);
2312 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2), 4);
2316 if (tree->reg1 != X86_EAX)
2317 x86_push_reg (s->code, X86_EAX);
2318 x86_push_reg (s->code, X86_ECX);
2319 x86_push_reg (s->code, X86_EDX);
2321 x86_push_imm (s->code, tree->data.m);
2322 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, arch_compile_method);
2323 x86_call_code (s->code, 0);
2324 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
2326 x86_pop_reg (s->code, X86_EDX);
2327 x86_pop_reg (s->code, X86_ECX);
2328 if (tree->reg1 != X86_EAX) {
2329 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
2330 x86_pop_reg (s->code, X86_EAX);
2332 PRINT_REG ("LDFTN", tree->reg1);
2336 reg: CALL_I4 (this, VFUNC_ADDR) {
2337 int lreg = tree->left->reg1;
2343 if (tree->left->op != MB_TERM_NOP) {
2344 mono_assert (lreg >= 0);
2345 x86_push_reg (s->code, lreg);
2348 if (tree->data.ci.vtype_num) {
2349 int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
2350 x86_lea_membase (s->code, treg, X86_EBP, offset);
2351 x86_push_reg (s->code, treg);
2354 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2355 x86_call_virtual (s->code, lreg,
2356 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
2358 if (tree->data.ci.args_size)
2359 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2361 PRINT_REG ("CALL_I4(VIRTUAL)", tree->reg1);
2363 mono_assert (tree->reg1 == X86_EAX);
2366 stmt: CALL_VOID (this, ADDR_G) {
2367 int lreg = tree->left->reg1;
2373 if (tree->left->op != MB_TERM_NOP) {
2374 mono_assert (lreg >= 0);
2375 x86_push_reg (s->code, lreg);
2376 x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
2379 if (tree->data.ci.vtype_num) {
2380 int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
2381 x86_lea_membase (s->code, treg, X86_EBP, offset);
2382 x86_push_reg (s->code, treg);
2385 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->right->data.p);
2386 x86_call_code (s->code, 0);
2388 if (tree->data.ci.args_size)
2389 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2392 stmt: CALL_VOID (this, INTF_ADDR) {
2393 int lreg = tree->left->reg1;
2399 if (tree->left->op != MB_TERM_NOP) {
2400 mono_assert (lreg >= 0);
2401 x86_push_reg (s->code, lreg);
2404 if (tree->data.ci.vtype_num) {
2405 int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
2406 x86_lea_membase (s->code, treg, X86_EBP, offset);
2407 x86_push_reg (s->code, treg);
2410 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2411 x86_mov_reg_membase (s->code, lreg, lreg,
2412 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
2413 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
2414 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
2416 if (tree->data.ci.args_size)
2417 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2420 stmt: CALL_VOID (this, VFUNC_ADDR) {
2421 int lreg = tree->left->reg1;
2427 if (tree->left->op != MB_TERM_NOP) {
2428 mono_assert (lreg >= 0);
2429 x86_push_reg (s->code, lreg);
2432 if (tree->data.ci.vtype_num) {
2433 int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
2434 x86_lea_membase (s->code, treg, X86_EBP, offset);
2435 x86_push_reg (s->code, treg);
2438 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2439 x86_call_virtual (s->code, lreg,
2440 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
2442 if (tree->data.ci.args_size)
2443 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
2446 stmt: SWITCH (reg) {
2448 guint32 *jt = (guint32 *)tree->data.p;
2450 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, jt [0]);
2451 offset = 6 + (guint32)s->code;
2452 x86_branch32 (s->code, X86_CC_GE, jt [jt [0] + 1] - offset, FALSE);
2454 x86_mov_reg_memindex (s->code, X86_EAX, X86_NOBASEREG,
2455 tree->data.i + 4, tree->left->reg1, 2, 4);
2456 x86_jump_reg (s->code, X86_EAX);
2463 reg: CONV_I1 (lreg) {
2464 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
2467 reg: CONV_U1 (lreg) {
2468 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
2471 reg: CONV_I2 (lreg) {
2472 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
2475 reg: CONV_U2 (lreg) {
2476 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
2479 reg: CONV_I4 (lreg) {
2480 if (tree->reg1 != tree->left->reg1)
2481 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2484 reg: CONV_U4 (lreg) {
2485 if (tree->reg1 != tree->left->reg1)
2486 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2490 reg: CONV_OVF_I4 (lreg){
2491 guint8 *start = s->code;
2492 guchar* o1, *o2, *o3, *o4, *o5;
2496 * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000
2498 for (i = 0; i < 2; i++) {
2501 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
2503 /* If the low word top bit is set, see if we are negative */
2504 x86_branch8 (s->code, X86_CC_LT, o3 - o1, TRUE);
2507 /* We are not negative (no top bit set, check for our top word to be zero */
2508 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
2509 x86_branch8 (s->code, X86_CC_EQ, o4 - o2, TRUE);
2512 /* throw exception */
2513 x86_push_imm (s->code, "OverflowException");
2514 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS,
2515 arch_get_throw_exception_by_name ());
2516 x86_call_code (s->code, 0);
2519 /* our top bit is set, check that top word is 0xfffffff */
2520 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg2, 0xffffffff);
2523 /* nope, emit exception */
2524 x86_branch8 (s->code, X86_CC_NE, o2 - o5, TRUE);
2527 if (tree->reg1 != tree->left->reg1)
2528 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2531 reg: CONV_OVF_I4 (lreg){
2532 guint8 *br [3], *label [1];
2535 * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000
2537 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
2539 /* If the low word top bit is set, see if we are negative */
2540 br [0] = s->code; x86_branch8 (s->code, X86_CC_LT, 0, TRUE);
2542 /* We are not negative (no top bit set, check for our top word to be zero */
2543 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
2544 br [1] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, TRUE);
2545 label [0] = s->code;
2547 /* throw exception */
2548 x86_push_imm (s->code, "OverflowException");
2549 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS,
2550 arch_get_throw_exception_by_name ());
2551 x86_call_code (s->code, 0);
2553 x86_patch (br [0], s->code);
2554 /* our top bit is set, check that top word is 0xfffffff */
2555 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg2, 0xffffffff);
2557 x86_patch (br [1], s->code);
2558 /* nope, emit exception */
2559 br [2] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
2560 x86_patch (br [2], label [0]);
2562 if (tree->reg1 != tree->left->reg1)
2563 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2566 reg: CONV_OVF_U4 (lreg) {
2567 /* Keep in sync with CONV_OVF_I4_UN below, they are the same on 32-bit machines */
2568 /* top word must be 0 */
2569 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
2570 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
2571 if (tree->reg1 != tree->left->reg1)
2572 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2575 reg: CONV_OVF_I4_UN (lreg) {
2576 /* Keep in sync with CONV_OVF_U4 above, they are the same on 32-bit machines */
2577 /* top word must be 0 */
2578 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
2579 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
2580 if (tree->reg1 != tree->left->reg1)
2581 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2587 x86_mov_reg_imm (s->code, tree->reg1, *((gint32 *)&tree->data.p));
2588 x86_mov_reg_imm (s->code, tree->reg2, *((gint32 *)&tree->data.p + 1));
2591 lreg: CONV_I8 (coni4) {
2592 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
2594 if (tree->left->data.i >= 0)
2595 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2597 x86_mov_reg_imm (s->code, tree->reg2, -1);
2600 lreg: CONV_I8 (reg) {
2603 if (tree->reg1 != tree->left->reg1)
2604 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2606 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2607 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
2608 x86_branch8 (s->code, X86_CC_GE, 5, TRUE);
2610 x86_mov_reg_imm (s->code, tree->reg2, -1);
2611 mono_assert ((s->code - i1) == 5);
2614 lreg: CONV_U8 (coni4) 1 {
2615 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
2616 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2619 lreg: CONV_U8 (reg) {
2620 if (tree->reg1 != tree->left->reg1)
2621 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2622 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2625 lreg: CONV_OVF_U8 (coni4) {
2626 if (tree->left->data.i < 0){
2627 x86_push_imm (s->code, "OverflowException");
2628 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS,
2629 arch_get_throw_exception_by_name ());
2630 x86_call_code (s->code, 0);
2632 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
2633 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2637 lreg: CONV_OVF_I8_UN (coni4) {
2638 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
2639 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2642 lreg: CONV_OVF_U8 (reg) {
2643 x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
2644 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
2646 if (tree->reg1 != tree->left->reg1)
2647 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2648 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2651 lreg: CONV_OVF_I8_UN (reg) {
2652 /* Convert uint value into int64, we pass everything */
2653 if (tree->reg1 != tree->left->reg1)
2654 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2655 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2658 stmt: STIND_I8 (addr, lreg) {
2660 switch (tree->left->data.ainfo.amode) {
2663 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
2664 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset + 4, tree->right->reg2, 4);
2668 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
2669 tree->left->data.ainfo.offset, tree->right->reg1, 4);
2670 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
2671 tree->left->data.ainfo.offset + 4, tree->right->reg2, 4);
2674 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
2675 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2676 tree->right->reg1, 4);
2677 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset + 4,
2678 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2679 tree->right->reg2, 4);
2682 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
2683 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2684 tree->right->reg1, 4);
2685 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset + 4,
2686 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2687 tree->right->reg2, 4);
2692 stmt: REMOTE_STIND_I8 (reg, lreg) {
2696 x86_push_reg (s->code, tree->right->reg1);
2697 x86_mov_reg_membase (s->code, tree->right->reg1, tree->left->reg1, 0, 4);
2698 x86_alu_membase_imm (s->code, X86_CMP, tree->right->reg1, 0, ((int)mono_defaults.transparent_proxy_class));
2699 x86_pop_reg (s->code, tree->right->reg1);
2701 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
2703 /* this is a transparent proxy - remote the call */
2705 /* save value to stack */
2706 x86_push_reg (s->code, tree->right->reg2);
2707 x86_push_reg (s->code, tree->right->reg1);
2709 x86_push_reg (s->code, X86_ESP);
2710 x86_push_imm (s->code, tree->data.fi.field);
2711 x86_push_imm (s->code, tree->data.fi.klass);
2712 x86_push_reg (s->code, tree->left->reg1);
2713 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
2714 x86_call_code (s->code, 0);
2715 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 24);
2717 br [1] = s->code; x86_jump8 (s->code, 0);
2719 x86_patch (br [0], s->code);
2720 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
2721 tree->data.fi.field->offset;
2722 x86_mov_membase_reg (s->code, tree->left->reg1, offset, tree->right->reg1, 4);
2723 x86_mov_membase_reg (s->code, tree->left->reg1, offset + 4, tree->right->reg2, 4);
2725 x86_patch (br [1], s->code);
2729 # an addr can use two address register (base and index register). The must take care
2730 # that we do not override them (thus the use of x86_lea)
2731 lreg: LDIND_I8 (addr) {
2733 switch (tree->left->data.ainfo.amode) {
2736 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
2737 x86_mov_reg_mem (s->code, tree->reg2, tree->left->data.ainfo.offset + 4, 4);
2741 x86_lea_membase (s->code, tree->reg2, tree->left->data.ainfo.basereg,
2742 tree->left->data.ainfo.offset);
2743 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
2744 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
2747 x86_lea_memindex (s->code, tree->reg2, X86_NOBASEREG, tree->left->data.ainfo.offset,
2748 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift);
2749 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
2750 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
2753 x86_lea_memindex (s->code, tree->reg2, tree->left->data.ainfo.basereg,
2754 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
2755 tree->left->data.ainfo.shift);
2756 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
2757 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
2760 PRINT_REG ("LDIND_I8_0", tree->reg1);
2761 PRINT_REG ("LDIND_I8_1", tree->reg2);
2764 lreg: SHR (lreg, coni4) {
2765 if (tree->right->data.i < 32) {
2766 x86_shrd_reg_imm (s->code, tree->left->reg1, tree->left->reg2, tree->right->data.i);
2767 x86_shift_reg_imm (s->code, X86_SAR, tree->left->reg2, tree->right->data.i);
2768 if (tree->reg1 != tree->left->reg1)
2769 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2770 if (tree->reg2 != tree->left->reg2)
2771 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2772 } else if (tree->right->data.i < 64) {
2773 if (tree->reg1 != tree->left->reg2)
2774 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg2, 4);
2775 if (tree->reg2 != tree->left->reg2)
2776 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2777 x86_shift_reg_imm (s->code, X86_SAR, tree->reg2, 31);
2778 x86_shift_reg_imm (s->code, X86_SAR, tree->reg1, (tree->right->data.i - 32));
2779 } /* else unspecified result */
2782 lreg: SHR_UN (lreg, coni4) {
2783 if (tree->right->data.i < 32) {
2784 x86_shrd_reg_imm (s->code, tree->left->reg1, tree->left->reg2, tree->right->data.i);
2785 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg2, tree->right->data.i);
2786 if (tree->reg1 != tree->left->reg1)
2787 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2788 if (tree->reg2 != tree->left->reg2)
2789 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2790 } else if (tree->right->data.i < 64) {
2791 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg2, 4);
2792 x86_shift_reg_imm (s->code, X86_SHR, tree->reg1, (tree->right->data.i - 32));
2793 x86_mov_reg_imm (s->code, tree->reg2, 0);
2794 } /* else unspecified result */
2797 lreg: SHR (lreg, reg) {
2800 if (tree->right->reg1 != X86_ECX)
2801 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
2803 x86_shrd_reg (s->code, tree->left->reg1, tree->left->reg2);
2804 x86_shift_reg (s->code, X86_SAR, tree->left->reg2);
2805 x86_test_reg_imm (s->code, X86_ECX, 32);
2806 br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
2807 x86_mov_reg_reg (s->code, tree->left->reg1, tree->left->reg2, 4);
2808 x86_shift_reg_imm (s->code, X86_SAR, tree->reg2, 31);
2809 x86_patch (br [0], s->code);
2811 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2814 lreg: SHR_UN (lreg, reg) {
2817 if (tree->right->reg1 != X86_ECX)
2818 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
2820 x86_shrd_reg (s->code, tree->left->reg1, tree->left->reg2);
2821 x86_shift_reg (s->code, X86_SHR, tree->left->reg2);
2822 x86_test_reg_imm (s->code, X86_ECX, 32);
2823 br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
2824 x86_mov_reg_reg (s->code, tree->left->reg1, tree->left->reg2, 4);
2825 x86_shift_reg_imm (s->code, X86_SHR, tree->reg2, 31);
2826 x86_patch (br [0], s->code);
2828 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2831 lreg: SHL (lreg, coni4) {
2832 if (tree->right->data.i < 32) {
2833 x86_shld_reg_imm (s->code, tree->left->reg2, tree->left->reg1, tree->right->data.i);
2834 x86_shift_reg_imm (s->code, X86_SHL, tree->left->reg1, tree->right->data.i);
2835 if (tree->reg1 != tree->left->reg1)
2836 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2837 if (tree->reg2 != tree->left->reg2)
2838 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2839 } else if (tree->right->data.i < 64) {
2840 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg1, 4);
2841 x86_shift_reg_imm (s->code, X86_SHL, tree->reg2, (tree->right->data.i - 32));
2842 x86_alu_reg_reg (s->code, X86_XOR, tree->reg1, tree->reg1);
2843 } /* else unspecified result */
2846 lreg: SHL (lreg, reg) {
2849 if (tree->right->reg1 != X86_ECX)
2850 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
2852 x86_shld_reg (s->code, tree->left->reg2, tree->left->reg1);
2853 x86_shift_reg (s->code, X86_SHL, tree->left->reg1);
2854 x86_test_reg_imm (s->code, X86_ECX, 32);
2855 br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
2856 x86_mov_reg_reg (s->code, tree->left->reg2, tree->left->reg1, 4);
2857 x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->left->reg1);
2858 x86_patch (br [0], s->code);
2860 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2863 lreg: ADD (lreg, lreg) {
2864 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
2865 x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
2867 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2870 lreg: ADD_OVF (lreg, lreg) {
2871 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
2872 x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
2873 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
2875 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2878 lreg: ADD_OVF_UN (lreg, lreg) {
2879 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
2880 x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
2881 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
2883 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2886 lreg: SUB (lreg, lreg) {
2887 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
2888 x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
2890 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2893 lreg: SUB_OVF (lreg, lreg) {
2894 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
2895 x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
2896 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
2898 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2901 lreg: SUB_OVF_UN (lreg, lreg) {
2902 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
2903 x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
2904 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
2906 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2909 lreg: AND (lreg, lreg) {
2910 x86_alu_reg_reg (s->code, X86_AND, tree->left->reg1, tree->right->reg1);
2911 x86_alu_reg_reg (s->code, X86_AND, tree->left->reg2, tree->right->reg2);
2913 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2916 lreg: OR (lreg, lreg) {
2917 x86_alu_reg_reg (s->code, X86_OR, tree->left->reg1, tree->right->reg1);
2918 x86_alu_reg_reg (s->code, X86_OR, tree->left->reg2, tree->right->reg2);
2920 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2923 lreg: XOR (lreg, lreg) {
2924 x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->right->reg1);
2925 x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg2, tree->right->reg2);
2927 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2931 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2933 x86_neg_reg (s->code, tree->reg1);
2934 x86_alu_reg_imm (s->code, X86_ADC, tree->reg2, 0);
2935 x86_neg_reg (s->code, tree->reg2);
2939 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
2941 x86_not_reg (s->code, tree->reg1);
2942 x86_not_reg (s->code, tree->reg2);
2945 lreg: MUL (lreg, lreg) {
2946 if (mono_regset_reg_used (s->rs, X86_ECX))
2947 x86_push_reg (s->code, X86_ECX);
2949 x86_push_reg (s->code, tree->right->reg2);
2950 x86_push_reg (s->code, tree->right->reg1);
2951 x86_push_reg (s->code, tree->left->reg2);
2952 x86_push_reg (s->code, tree->left->reg1);
2953 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_llmult);
2954 x86_call_code (s->code, 0);
2955 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2957 if (mono_regset_reg_used (s->rs, X86_ECX))
2958 x86_pop_reg (s->code, X86_ECX);
2960 mono_assert (tree->reg1 == X86_EAX &&
2961 tree->reg2 == X86_EDX);
2964 lreg: MUL_OVF (lreg, lreg) {
2965 if (mono_regset_reg_used (s->rs, X86_ECX))
2966 x86_push_reg (s->code, X86_ECX);
2968 x86_push_reg (s->code, tree->right->reg2);
2969 x86_push_reg (s->code, tree->right->reg1);
2970 x86_push_reg (s->code, tree->left->reg2);
2971 x86_push_reg (s->code, tree->left->reg1);
2972 /* pass a pointer to store the resulting exception -
2973 * ugly, but it works */
2974 x86_push_reg (s->code, X86_ESP);
2975 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_llmult_ovf);
2976 x86_call_code (s->code, 0);
2977 x86_mov_reg_membase (s->code, X86_ECX, X86_ESP, 4, 4);
2978 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
2979 x86_alu_reg_imm (s->code, X86_CMP, X86_ECX, 0);
2981 /* cond. emit exception */
2982 x86_branch8 (s->code, X86_CC_EQ, 7, FALSE);
2983 x86_push_reg (s->code, X86_ECX);
2984 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, arch_get_throw_exception ());
2985 x86_call_code (s->code, 0);
2987 if (mono_regset_reg_used (s->rs, X86_ECX))
2988 x86_pop_reg (s->code, X86_ECX);
2990 mono_assert (tree->reg1 == X86_EAX &&
2991 tree->reg2 == X86_EDX);
2994 lreg: MUL_OVF_UN (lreg, lreg) {
2995 if (mono_regset_reg_used (s->rs, X86_ECX))
2996 x86_push_reg (s->code, X86_ECX);
2998 x86_push_reg (s->code, tree->right->reg2);
2999 x86_push_reg (s->code, tree->right->reg1);
3000 x86_push_reg (s->code, tree->left->reg2);
3001 x86_push_reg (s->code, tree->left->reg1);
3002 /* pass a pointer to store the resulting exception -
3003 * ugly, but it works */
3004 x86_push_reg (s->code, X86_ESP);
3005 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_llmult_ovf_un);
3006 x86_call_code (s->code, 0);
3007 x86_mov_reg_membase (s->code, X86_ECX, X86_ESP, 4, 4);
3008 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
3009 x86_alu_reg_imm (s->code, X86_CMP, X86_ECX, 0);
3011 /* cond. emit exception */
3012 x86_branch8 (s->code, X86_CC_EQ, 7, FALSE);
3013 x86_push_reg (s->code, X86_ECX);
3014 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, arch_get_throw_exception ());
3015 x86_call_code (s->code, 0);
3017 if (mono_regset_reg_used (s->rs, X86_ECX))
3018 x86_pop_reg (s->code, X86_ECX);
3020 mono_assert (tree->reg1 == X86_EAX &&
3021 tree->reg2 == X86_EDX);
3024 lreg: DIV (lreg, lreg) {
3025 if (mono_regset_reg_used (s->rs, X86_ECX))
3026 x86_push_reg (s->code, X86_ECX);
3028 x86_push_reg (s->code, tree->right->reg2);
3029 x86_push_reg (s->code, tree->right->reg1);
3030 x86_push_reg (s->code, tree->left->reg2);
3031 x86_push_reg (s->code, tree->left->reg1);
3032 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_lldiv);
3033 x86_call_code (s->code, 0);
3034 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
3036 if (mono_regset_reg_used (s->rs, X86_ECX))
3037 x86_pop_reg (s->code, X86_ECX);
3039 mono_assert (tree->reg1 == X86_EAX &&
3040 tree->reg2 == X86_EDX);
3043 lreg: REM (lreg, lreg) {
3044 if (mono_regset_reg_used (s->rs, X86_ECX))
3045 x86_push_reg (s->code, X86_ECX);
3047 x86_push_reg (s->code, tree->right->reg2);
3048 x86_push_reg (s->code, tree->right->reg1);
3049 x86_push_reg (s->code, tree->left->reg2);
3050 x86_push_reg (s->code, tree->left->reg1);
3051 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_llrem);
3052 x86_call_code (s->code, 0);
3053 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
3055 if (mono_regset_reg_used (s->rs, X86_ECX))
3056 x86_pop_reg (s->code, X86_ECX);
3058 mono_assert (tree->reg1 == X86_EAX &&
3059 tree->reg2 == X86_EDX);
3062 lreg: DIV_UN (lreg, lreg) {
3063 if (mono_regset_reg_used (s->rs, X86_ECX))
3064 x86_push_reg (s->code, X86_ECX);
3066 x86_push_reg (s->code, tree->right->reg2);
3067 x86_push_reg (s->code, tree->right->reg1);
3068 x86_push_reg (s->code, tree->left->reg2);
3069 x86_push_reg (s->code, tree->left->reg1);
3070 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_lldiv_un);
3071 x86_call_code (s->code, 0);
3072 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
3074 if (mono_regset_reg_used (s->rs, X86_ECX))
3075 x86_pop_reg (s->code, X86_ECX);
3077 mono_assert (tree->reg1 == X86_EAX &&
3078 tree->reg2 == X86_EDX);
3081 lreg: REM_UN (lreg, lreg) {
3082 if (mono_regset_reg_used (s->rs, X86_ECX))
3083 x86_push_reg (s->code, X86_ECX);
3085 x86_push_reg (s->code, tree->right->reg2);
3086 x86_push_reg (s->code, tree->right->reg1);
3087 x86_push_reg (s->code, tree->left->reg2);
3088 x86_push_reg (s->code, tree->left->reg1);
3089 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_llrem_un);
3090 x86_call_code (s->code, 0);
3091 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
3093 if (mono_regset_reg_used (s->rs, X86_ECX))
3094 x86_pop_reg (s->code, X86_ECX);
3096 mono_assert (tree->reg1 == X86_EAX &&
3097 tree->reg2 == X86_EDX);
3100 lreg: CALL_I8 (this, ADDR_G) {
3101 int lreg = tree->left->reg1;
3107 if (tree->left->op != MB_TERM_NOP) {
3108 mono_assert (lreg >= 0);
3109 x86_push_reg (s->code, lreg);
3110 x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
3113 if (tree->data.ci.vtype_num) {
3114 int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
3115 x86_lea_membase (s->code, treg, X86_EBP, offset);
3116 x86_push_reg (s->code, treg);
3119 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->right->data.p);
3120 x86_call_code (s->code, 0);
3122 if (tree->data.ci.args_size)
3123 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
3125 mono_assert (tree->reg1 == X86_EAX);
3126 mono_assert (tree->reg2 == X86_EDX);
3129 lreg: CALL_I8 (this, VFUNC_ADDR) {
3130 int lreg = tree->left->reg1;
3136 if (tree->left->op != MB_TERM_NOP) {
3137 mono_assert (lreg >= 0);
3138 x86_push_reg (s->code, lreg);
3141 if (tree->data.ci.vtype_num) {
3142 int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
3143 x86_lea_membase (s->code, treg, X86_EBP, offset);
3144 x86_push_reg (s->code, treg);
3147 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
3148 x86_call_virtual (s->code, lreg,
3149 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
3151 if (tree->data.ci.args_size)
3152 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
3154 PRINT_REG ("CALL0_I8(VIRTUAL)", tree->reg1);
3155 PRINT_REG ("CALL1_I8(VIRTUAL)", tree->reg2);
3157 mono_assert (tree->reg1 == X86_EAX);
3158 mono_assert (tree->reg2 == X86_EDX);
3161 lreg: CALL_I8 (this, INTF_ADDR) {
3162 int lreg = tree->left->reg1;
3168 if (tree->left->op != MB_TERM_NOP) {
3169 mono_assert (lreg >= 0);
3170 x86_push_reg (s->code, lreg);
3173 if (tree->data.ci.vtype_num) {
3174 int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
3175 x86_lea_membase (s->code, treg, X86_EBP, offset);
3176 x86_push_reg (s->code, treg);
3179 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
3180 x86_mov_reg_membase (s->code, lreg, lreg,
3181 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
3182 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
3183 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
3185 if (tree->data.ci.args_size)
3186 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
3188 PRINT_REG ("CALL_I8(INTERFACE)", tree->reg1);
3190 mono_assert (tree->reg1 == X86_EAX);
3191 mono_assert (tree->reg2 == X86_EDX);
3195 if (tree->left->reg1 != X86_EAX) {
3196 if (tree->left->reg2 != X86_EAX) {
3197 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
3198 if (tree->left->reg2 != X86_EDX)
3199 x86_mov_reg_reg (s->code, X86_EDX, tree->left->reg2, 4);
3201 x86_mov_reg_reg (s->code, X86_ECX, tree->left->reg2, 4);
3202 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
3203 x86_mov_reg_reg (s->code, X86_EDX, X86_ECX, 4);
3205 } else if (tree->left->reg2 != X86_EDX) {
3206 x86_mov_reg_reg (s->code, X86_EDX, tree->left->reg2, 4);
3209 if (!tree->last_instr) {
3210 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_EPILOG, NULL);
3211 x86_jump32 (s->code, 0);
3216 stmt: ARG_I8 (lreg) {
3217 x86_push_reg (s->code, tree->left->reg2);
3218 x86_push_reg (s->code, tree->left->reg1);
3221 reg: CSET (COMPARE (lreg, lreg)) {
3223 int lreg1, lreg2, rreg1, rreg2;
3225 lreg1 = tree->left->left->reg1;
3226 lreg2 = tree->left->left->reg2;
3227 rreg1 = tree->left->right->reg1;
3228 rreg2 = tree->left->right->reg2;
3231 if (tree->data.i == CEE_CEQ) {
3232 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3233 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3234 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3235 x86_patch (br [0], s->code);
3236 x86_set_reg (s->code, X86_CC_EQ, tree->reg1, FALSE);
3237 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
3241 switch (tree->data.i) {
3243 x86_alu_reg_reg (s->code, X86_CMP, rreg2, lreg2);
3244 br [0] = s->code; x86_branch8 (s->code, X86_CC_GT, 0, TRUE);
3245 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3246 x86_alu_reg_reg (s->code, X86_CMP, rreg1, lreg1);
3247 br [2] = s->code; x86_branch8 (s->code, X86_CC_GE, 0, FALSE);
3250 x86_alu_reg_reg (s->code, X86_CMP, rreg2, lreg2);
3251 br [0] = s->code; x86_branch8 (s->code, X86_CC_GT, 0, FALSE);
3252 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3253 x86_alu_reg_reg (s->code, X86_CMP, rreg1, lreg1);
3254 br [2] = s->code; x86_branch8 (s->code, X86_CC_GE, 0, FALSE);
3257 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3258 br [0] = s->code; x86_branch8 (s->code, X86_CC_GT, 0, TRUE);
3259 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3260 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3261 br [2] = s->code; x86_branch8 (s->code, X86_CC_GE, 0, FALSE);
3264 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3265 br [0] = s->code; x86_branch8 (s->code, X86_CC_GT, 0, FALSE);
3266 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3267 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3268 br [2] = s->code; x86_branch8 (s->code, X86_CC_GE, 0, FALSE);
3271 g_assert_not_reached ();
3274 /* set result to 1 */
3275 x86_patch (br [1], s->code);
3276 x86_mov_reg_imm (s->code, tree->reg1, 1);
3277 br [3] = s->code; x86_jump8 (s->code, 0);
3279 /* set result to 0 */
3280 x86_patch (br [0], s->code);
3281 x86_patch (br [2], s->code);
3282 x86_mov_reg_imm (s->code, tree->reg1, 0);
3284 x86_patch (br [3], s->code);
3287 stmt: CBRANCH (COMPARE (lreg, lreg)) {
3289 int lreg1, lreg2, rreg1, rreg2;
3291 lreg1 = tree->left->left->reg1;
3292 lreg2 = tree->left->left->reg2;
3293 rreg1 = tree->left->right->reg1;
3294 rreg2 = tree->left->right->reg2;
3296 switch (tree->data.bi.cond) {
3298 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3299 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3300 x86_branch32 (s->code, X86_CC_LT, 0, TRUE);
3301 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3302 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3303 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3304 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
3305 x86_patch (br [0], s->code);
3308 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3309 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3310 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
3311 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3312 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3313 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3314 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
3315 x86_patch (br [0], s->code);
3318 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3319 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3320 x86_branch32 (s->code, X86_CC_GT, 0, TRUE);
3321 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3322 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3323 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3324 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
3325 x86_patch (br [0], s->code);
3328 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3329 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3330 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
3331 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3332 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3333 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3334 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
3335 x86_patch (br [0], s->code);
3338 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3339 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3340 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3341 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3342 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
3343 x86_patch (br [0], s->code);
3346 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3347 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3348 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3349 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3350 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3351 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3354 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3355 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3356 x86_branch32 (s->code, X86_CC_GT, 0, TRUE);
3357 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3358 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3359 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3360 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3361 x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
3362 x86_patch (br [0], s->code);
3365 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3366 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3367 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
3368 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3369 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3370 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3371 x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
3372 x86_patch (br [0], s->code);
3375 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3376 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3377 x86_branch32 (s->code, X86_CC_LT, 0, TRUE);
3378 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3379 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3380 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3381 x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
3382 x86_patch (br [0], s->code);
3385 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3386 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3387 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
3388 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3389 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3390 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3391 x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
3392 x86_patch (br [0], s->code);
3395 g_assert_not_reached ();
3402 #stmt: STLOC (CONV_I4 (freg)) {
3404 # x86_fist_pop_membase (s->code, X86_EBP, tree->data.i, FALSE);
3407 reg: CONV_I1 (freg) {
3408 if (mono_use_fast_iconv) {
3409 mono_emit_fast_iconv(s, tree);
3410 x86_widen_reg (s->code, tree->reg1, tree->reg1, TRUE, FALSE);
3412 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3413 x86_fnstcw_membase(s->code, X86_ESP, 0);
3414 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3415 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3416 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3417 x86_fldcw_membase (s->code, X86_ESP, 2);
3418 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
3419 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
3420 x86_pop_reg (s->code, tree->reg1);
3421 x86_widen_reg (s->code, tree->reg1, tree->reg1, TRUE, FALSE);
3422 x86_fldcw_membase (s->code, X86_ESP, 0);
3423 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3427 reg: CONV_U1 (freg) {
3428 if (mono_use_fast_iconv) {
3429 mono_emit_fast_iconv(s, tree);
3430 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
3432 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3433 x86_fnstcw_membase(s->code, X86_ESP, 0);
3434 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3435 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3436 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3437 x86_fldcw_membase (s->code, X86_ESP, 2);
3438 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
3439 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
3440 x86_pop_reg (s->code, tree->reg1);
3441 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
3442 x86_fldcw_membase (s->code, X86_ESP, 0);
3443 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3447 reg: CONV_I2 (freg) {
3448 if (mono_use_fast_iconv) {
3449 mono_emit_fast_iconv(s, tree);
3450 x86_widen_reg (s->code, tree->reg1, tree->reg1, TRUE, TRUE);
3452 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3453 x86_fnstcw_membase(s->code, X86_ESP, 0);
3454 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3455 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3456 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3457 x86_fldcw_membase (s->code, X86_ESP, 2);
3458 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
3459 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
3460 x86_pop_reg (s->code, tree->reg1);
3461 x86_widen_reg (s->code, tree->reg1, tree->reg1, TRUE, TRUE);
3462 x86_fldcw_membase (s->code, X86_ESP, 0);
3463 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3467 reg: CONV_U2 (freg) {
3468 if (mono_use_fast_iconv) {
3469 mono_emit_fast_iconv(s, tree);
3470 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, TRUE);
3472 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3473 x86_fnstcw_membase(s->code, X86_ESP, 0);
3474 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3475 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3476 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3477 x86_fldcw_membase (s->code, X86_ESP, 2);
3478 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
3479 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
3480 x86_pop_reg (s->code, tree->reg1);
3481 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, TRUE);
3482 x86_fldcw_membase (s->code, X86_ESP, 0);
3483 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3487 reg: CONV_I4 (freg) {
3488 if (mono_use_fast_iconv) {
3489 mono_emit_fast_iconv(s, tree);
3491 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3492 x86_fnstcw_membase(s->code, X86_ESP, 0);
3493 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3494 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3495 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3496 x86_fldcw_membase (s->code, X86_ESP, 2);
3497 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
3498 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
3499 x86_pop_reg (s->code, tree->reg1);
3500 x86_fldcw_membase (s->code, X86_ESP, 0);
3501 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3505 reg: CONV_U4 (freg) {
3506 if (mono_use_fast_iconv) {
3507 mono_emit_fast_iconv(s, tree);
3509 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3510 x86_fnstcw_membase(s->code, X86_ESP, 0);
3511 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3512 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3513 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3514 x86_fldcw_membase (s->code, X86_ESP, 2);
3515 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
3516 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
3517 x86_pop_reg (s->code, tree->reg1);
3518 x86_fldcw_membase (s->code, X86_ESP, 0);
3519 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3523 lreg: CONV_I8 (freg) {
3524 if (mono_use_fast_iconv) {
3525 mono_emit_fast_iconv_i8(s, tree);
3527 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3528 x86_fnstcw_membase(s->code, X86_ESP, 0);
3529 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3530 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3531 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3532 x86_fldcw_membase (s->code, X86_ESP, 2);
3533 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
3534 x86_fist_pop_membase (s->code, X86_ESP, 0, TRUE);
3535 x86_pop_reg (s->code, tree->reg1);
3536 x86_pop_reg (s->code, tree->reg2);
3537 x86_fldcw_membase (s->code, X86_ESP, 0);
3538 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3542 lreg: CONV_U8 (freg) {
3543 if (mono_use_fast_iconv) {
3544 mono_emit_fast_iconv_i8(s, tree);
3546 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3547 x86_fnstcw_membase(s->code, X86_ESP, 0);
3548 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3549 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3550 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3551 x86_fldcw_membase (s->code, X86_ESP, 2);
3552 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
3553 x86_fist_pop_membase (s->code, X86_ESP, 0, TRUE);
3554 x86_pop_reg (s->code, tree->reg1);
3555 x86_pop_reg (s->code, tree->reg2);
3556 x86_fldcw_membase (s->code, X86_ESP, 0);
3557 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3561 reg: CSET (COMPARE (freg, freg)) {
3562 int treg = tree->reg1;
3564 if (treg != X86_EAX)
3565 x86_push_reg (s->code, X86_EAX);
3567 x86_fcompp (s->code);
3568 x86_fnstsw (s->code);
3569 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3571 switch (tree->data.i) {
3573 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
3574 x86_set_reg (s->code, X86_CC_EQ, treg, TRUE);
3575 x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
3578 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3579 x86_set_reg (s->code, X86_CC_EQ, treg, TRUE);
3580 x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
3583 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3584 x86_set_reg (s->code, X86_CC_EQ, treg, TRUE);
3585 x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
3588 x86_set_reg (s->code, X86_CC_EQ, treg, TRUE);
3589 x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
3592 x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
3593 x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
3596 g_assert_not_reached ();
3599 if (treg != X86_EAX)
3600 x86_pop_reg (s->code, X86_EAX);
3603 freg: CONV_R8 (freg) {
3607 freg: CONV_R4 (freg) {
3608 /* fixme: nothing to do ??*/
3611 freg: CONV_R8 (LDIND_I4 (ADDR_G)) {
3612 x86_fild (s->code, tree->left->left->data.p, FALSE);
3615 freg: CONV_R4 (reg) {
3616 x86_push_reg (s->code, tree->left->reg1);
3617 x86_fild_membase (s->code, X86_ESP, 0, FALSE);
3618 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3621 freg: CONV_R8 (reg) {
3622 x86_push_reg (s->code, tree->left->reg1);
3623 x86_fild_membase (s->code, X86_ESP, 0, FALSE);
3624 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3627 freg: CONV_R_UN (reg) {
3628 x86_push_imm (s->code, 0);
3629 x86_push_reg (s->code, tree->left->reg1);
3630 x86_fild_membase (s->code, X86_ESP, 0, TRUE);
3631 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
3634 freg: CONV_R_UN (lreg) {
3635 static guint8 mn[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x40 };
3638 /* load 64bit integer to FP stack */
3639 x86_push_imm (s->code, 0);
3640 x86_push_reg (s->code, tree->left->reg2);
3641 x86_push_reg (s->code, tree->left->reg1);
3642 x86_fild_membase (s->code, X86_ESP, 0, TRUE);
3643 /* store as 80bit FP value */
3644 x86_fst80_membase (s->code, X86_ESP, 0);
3646 /* test if lreg is negative */
3647 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
3648 br [0] = s->code; x86_branch8 (s->code, X86_CC_GEZ, 0, TRUE);
3650 /* add correction constant mn */
3651 x86_fld80_mem (s->code, mn);
3652 x86_fld80_membase (s->code, X86_ESP, 0);
3653 x86_fp_op_reg (s->code, X86_FADD, 1, TRUE);
3654 x86_fst80_membase (s->code, X86_ESP, 0);
3656 x86_patch (br [0], s->code);
3658 x86_fld80_membase (s->code, X86_ESP, 0);
3659 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
3662 freg: CONV_R4 (lreg) {
3663 x86_push_reg (s->code, tree->left->reg2);
3664 x86_push_reg (s->code, tree->left->reg1);
3665 x86_fild_membase (s->code, X86_ESP, 0, TRUE);
3666 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
3669 freg: CONV_R8 (lreg) {
3670 x86_push_reg (s->code, tree->left->reg2);
3671 x86_push_reg (s->code, tree->left->reg1);
3672 x86_fild_membase (s->code, X86_ESP, 0, TRUE);
3673 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
3677 float f = *(float *)tree->data.p;
3684 x86_fld (s->code, tree->data.p, FALSE);
3688 double d = *(double *)tree->data.p;
3695 x86_fld (s->code, tree->data.p, TRUE);
3698 freg: LDIND_R4 (addr) {
3700 switch (tree->left->data.ainfo.amode) {
3703 x86_fld (s->code, tree->left->data.ainfo.offset, FALSE);
3707 x86_fld_membase (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset, FALSE);
3710 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, X86_NOBASEREG,
3711 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
3712 tree->left->data.ainfo.shift);
3713 x86_fld_membase (s->code, tree->left->data.ainfo.indexreg, 0, FALSE);
3716 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, tree->left->data.ainfo.basereg,
3717 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
3718 tree->left->data.ainfo.shift);
3719 x86_fld_membase (s->code, tree->left->data.ainfo.indexreg, 0, FALSE);
3724 freg: LDIND_R8 (addr) {
3726 switch (tree->left->data.ainfo.amode) {
3729 x86_fld (s->code, tree->left->data.ainfo.offset, TRUE);
3733 x86_fld_membase (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset, TRUE);
3736 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, X86_NOBASEREG,
3737 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
3738 tree->left->data.ainfo.shift);
3739 x86_fld_membase (s->code, tree->left->data.ainfo.indexreg, 0, TRUE);
3742 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, tree->left->data.ainfo.basereg,
3743 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
3744 tree->left->data.ainfo.shift);
3745 x86_fld_membase (s->code, tree->left->data.ainfo.indexreg, 0, TRUE);
3751 freg: ADD (freg, freg) {
3752 x86_fp_op_reg (s->code, X86_FADD, 1, TRUE);
3755 freg: SUB (freg, freg) {
3756 x86_fp_op_reg (s->code, X86_FSUB, 1, TRUE);
3759 freg: MUL (freg, freg) {
3760 x86_fp_op_reg (s->code, X86_FMUL, 1, TRUE);
3763 freg: DIV (freg, freg) {
3764 x86_fp_op_reg (s->code, X86_FDIV, 1, TRUE);
3767 freg: REM (freg, freg) {
3770 /* we need to exchange ST(0) with ST(1) */
3771 x86_fxch (s->code, 1);
3773 /* this requires a loop, because fprem1 somtimes
3774 * returns a partial remainder */
3776 x86_fprem1 (s->code);
3777 x86_fnstsw (s->code);
3778 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x0400);
3780 x86_branch8 (s->code, X86_CC_NE, l1 - l2, FALSE);
3783 x86_fstp (s->code, 1);
3792 stmt: STIND_R4 (addr, freg) {
3794 switch (tree->left->data.ainfo.amode) {
3797 x86_fst (s->code, tree->left->data.ainfo.offset, FALSE, TRUE);
3801 x86_fst_membase (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
3805 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, X86_NOBASEREG,
3806 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
3807 tree->left->data.ainfo.shift);
3808 x86_fst_membase (s->code, tree->left->data.ainfo.indexreg, 0, FALSE, TRUE);
3811 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, tree->left->data.ainfo.basereg,
3812 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
3813 tree->left->data.ainfo.shift);
3814 x86_fst_membase (s->code, tree->left->data.ainfo.indexreg, 0, FALSE, TRUE);
3819 stmt: STIND_R8 (addr, freg) {
3821 switch (tree->left->data.ainfo.amode) {
3824 x86_fst (s->code, tree->left->data.ainfo.offset, TRUE, TRUE);
3828 x86_fst_membase (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
3832 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, X86_NOBASEREG,
3833 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
3834 tree->left->data.ainfo.shift);
3835 x86_fst_membase (s->code, tree->left->data.ainfo.indexreg, 0, TRUE, TRUE);
3838 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, tree->left->data.ainfo.basereg,
3839 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
3840 tree->left->data.ainfo.shift);
3841 x86_fst_membase (s->code, tree->left->data.ainfo.indexreg, 0, TRUE, TRUE);
3846 stmt: REMOTE_STIND_R4 (reg, freg) {
3849 int lreg = tree->left->reg1;
3855 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
3856 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
3857 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3859 /* this is a transparent proxy - remote the call */
3861 /* save value to stack */
3862 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3863 x86_fst_membase (s->code, X86_ESP, 0, FALSE, TRUE);
3865 x86_push_reg (s->code, X86_ESP);
3866 x86_push_imm (s->code, tree->data.fi.field);
3867 x86_push_imm (s->code, tree->data.fi.klass);
3868 x86_push_reg (s->code, lreg);
3869 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
3870 x86_call_code (s->code, 0);
3871 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
3873 br [1] = s->code; x86_jump8 (s->code, 0);
3875 x86_patch (br [0], s->code);
3876 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
3877 tree->data.fi.field->offset;
3878 x86_fst_membase (s->code, lreg, offset, FALSE, TRUE);
3880 x86_patch (br [1], s->code);
3883 stmt: REMOTE_STIND_R8 (reg, freg) {
3886 int lreg = tree->left->reg1;
3892 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
3893 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
3894 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3896 /* this is a transparent proxy - remote the call */
3898 /* save value to stack */
3899 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
3900 x86_fst_membase (s->code, X86_ESP, 0, TRUE, TRUE);
3902 x86_push_reg (s->code, X86_ESP);
3903 x86_push_imm (s->code, tree->data.fi.field);
3904 x86_push_imm (s->code, tree->data.fi.klass);
3905 x86_push_reg (s->code, lreg);
3906 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
3907 x86_call_code (s->code, 0);
3908 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 24);
3910 br [1] = s->code; x86_jump8 (s->code, 0);
3912 x86_patch (br [0], s->code);
3913 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
3914 tree->data.fi.field->offset;
3915 x86_fst_membase (s->code, lreg, offset, TRUE, TRUE);
3917 x86_patch (br [1], s->code);
3920 stmt: ARG_R4 (freg) {
3921 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3922 x86_fst_membase (s->code, X86_ESP, 0, FALSE, TRUE);
3925 stmt: ARG_R8 (freg) {
3926 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
3927 x86_fst_membase (s->code, X86_ESP, 0, TRUE, TRUE);
3930 # fixme: we need to implement unordered and ordered compares
3932 stmt: CBRANCH (COMPARE (freg, freg)) {
3934 x86_fcompp (s->code);
3935 x86_fnstsw (s->code);
3936 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3938 switch (tree->data.bi.cond) {
3940 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3941 x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
3944 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3945 x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
3948 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3949 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3950 x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
3953 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3954 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3955 x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
3958 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
3959 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3960 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
3963 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
3964 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3965 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3968 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3969 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3972 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3973 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3976 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3977 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3978 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3981 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3982 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3983 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3986 g_assert_not_reached ();
3990 freg: CALL_R8 (this, ADDR_G) {
3991 int lreg = tree->left->reg1;
3997 if (tree->left->op != MB_TERM_NOP) {
3998 mono_assert (lreg >= 0);
3999 x86_push_reg (s->code, lreg);
4000 x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
4003 if (tree->data.ci.vtype_num) {
4004 int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
4005 x86_lea_membase (s->code, treg, X86_EBP, offset);
4006 x86_push_reg (s->code, treg);
4009 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->right->data.p);
4010 x86_call_code (s->code, 0);
4012 if (tree->data.ci.args_size)
4013 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
4016 freg: CALL_R8 (this, INTF_ADDR) {
4017 int lreg = tree->left->reg1;
4023 if (tree->left->op != MB_TERM_NOP) {
4024 mono_assert (lreg >= 0);
4025 x86_push_reg (s->code, lreg);
4028 if (tree->data.ci.vtype_num) {
4029 int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
4030 x86_lea_membase (s->code, treg, X86_EBP, offset);
4031 x86_push_reg (s->code, treg);
4034 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
4035 x86_mov_reg_membase (s->code, lreg, lreg,
4036 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
4037 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
4038 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
4040 if (tree->data.ci.args_size)
4041 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
4044 freg: CALL_R8 (this, VFUNC_ADDR) {
4045 int lreg = tree->left->reg1;
4051 if (tree->left->op != MB_TERM_NOP) {
4052 mono_assert (lreg >= 0);
4053 x86_push_reg (s->code, lreg);
4056 if (tree->data.ci.vtype_num) {
4057 int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
4058 x86_lea_membase (s->code, treg, X86_EBP, offset);
4059 x86_push_reg (s->code, treg);
4062 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
4063 x86_call_virtual (s->code, lreg,
4064 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
4066 if (tree->data.ci.args_size)
4067 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
4071 if (!tree->last_instr) {
4072 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_EPILOG, NULL);
4073 x86_jump32 (s->code, 0);
4077 # support for value types
4079 reg: LDIND_OBJ (reg) {
4080 if (tree->left->reg1 != tree->reg1)
4081 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
4084 stmt: STIND_OBJ (reg, reg) {
4085 mono_assert (tree->data.i > 0);
4087 x86_push_imm (s->code, tree->data.i);
4088 x86_push_reg (s->code, tree->right->reg1);
4089 x86_push_reg (s->code, tree->left->reg1);
4090 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, MEMCOPY);
4091 x86_call_code (s->code, 0);
4092 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
4095 stmt: REMOTE_STIND_OBJ (reg, reg) {
4098 int lreg = tree->left->reg1;
4099 int rreg = tree->right->reg1;
4108 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
4109 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
4110 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
4112 /* this is a transparent proxy - remote the call */
4114 x86_push_reg (s->code, rreg);
4115 x86_push_imm (s->code, tree->data.fi.field);
4116 x86_push_imm (s->code, tree->data.fi.klass);
4117 x86_push_reg (s->code, lreg);
4118 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
4119 x86_call_code (s->code, 0);
4120 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
4122 br [1] = s->code; x86_jump8 (s->code, 0);
4124 x86_patch (br [0], s->code);
4125 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
4126 tree->data.fi.field->offset;
4128 x86_push_imm (s->code, mono_class_value_size (tree->data.fi.klass, NULL));
4129 x86_push_reg (s->code, tree->right->reg1);
4130 x86_alu_reg_imm (s->code, X86_ADD, tree->left->reg1, sizeof (MonoObject));
4131 x86_push_reg (s->code, tree->left->reg1);
4132 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, MEMCOPY);
4133 x86_call_code (s->code, 0);
4134 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
4136 x86_patch (br [1], s->code);
4139 stmt: ARG_OBJ (coni4) {
4140 x86_push_imm (s->code, tree->left->data.i);
4143 stmt: ARG_OBJ (reg) {
4144 int size = tree->data.i;
4147 mono_assert (size > 0);
4152 /* reserve space for the argument */
4153 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);
4155 x86_push_reg (s->code, X86_EAX);
4156 x86_push_reg (s->code, X86_EDX);
4157 x86_push_reg (s->code, X86_ECX);
4159 x86_push_imm (s->code, size);
4160 x86_push_reg (s->code, tree->left->reg1);
4161 x86_lea_membase (s->code, X86_EAX, X86_ESP, 5*4);
4162 x86_push_reg (s->code, X86_EAX);
4164 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, MEMCOPY);
4165 x86_call_code (s->code, 0);
4166 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
4168 x86_pop_reg (s->code, X86_ECX);
4169 x86_pop_reg (s->code, X86_EDX);
4170 x86_pop_reg (s->code, X86_EAX);
4173 stmt: RET_OBJ (reg) {
4174 int size = tree->data.i;
4176 x86_push_imm (s->code, size);
4177 x86_push_reg (s->code, tree->left->reg1);
4178 x86_push_membase (s->code, X86_EBP, 8);
4181 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, MEMCOPY);
4182 x86_call_code (s->code, 0);
4184 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
4186 if (!tree->last_instr) {
4187 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_EPILOG, NULL);
4188 x86_jump32 (s->code, 0);
4197 mono_llmult (gint64 a, gint64 b)
4203 mono_llmult_ovf_un (gpointer *exc, guint32 al, guint32 ah, guint32 bl, guint32 bh)
4207 // fixme: this is incredible slow
4210 goto raise_exception;
4212 res = (guint64)al * (guint64)bl;
4214 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
4216 if (t1 > 0xffffffff)
4217 goto raise_exception;
4219 res += ((guint64)t1) << 32;
4225 *exc = mono_get_exception_overflow ();
4230 mono_llmult_ovf (gpointer *exc, guint32 al, gint32 ah, guint32 bl, gint32 bh)
4234 // fixme: check for overflow
4236 res = (gint64)al * (gint64)bl;
4238 t1 = (gint64)ah * bl + al * (gint64)bh;
4240 res += ((gint64)t1) << 32;
4246 *exc = mono_get_exception_overflow ();
4252 mono_lldiv (gint64 a, gint64 b)
4258 mono_llrem (gint64 a, gint64 b)
4264 mono_lldiv_un (guint64 a, guint64 b)
4270 mono_llrem_un (guint64 a, guint64 b)
4276 mono_ctree_new (MonoMemPool *mp, int op, MBTree *left, MBTree *right)
4278 MBTree *t = mono_mempool_alloc0 (mp, sizeof (MBTree));
4286 t->svt = VAL_UNKNOWN;
4292 mono_ctree_new_leaf (MonoMemPool *mp, int op)
4294 return mono_ctree_new (mp, op, NULL, NULL);
4298 mono_array_new_wrapper (MonoClass *eclass, guint32 n)
4300 MonoDomain *domain = mono_domain_get ();
4302 return mono_array_new (domain, eclass, n);
4306 mono_object_new_wrapper (MonoClass *klass)
4308 MonoDomain *domain = mono_domain_get ();
4310 return mono_object_new (domain, klass);
4314 mono_ldstr_wrapper (MonoImage *image, guint32 ind)
4316 MonoDomain *domain = mono_domain_get ();
4318 return mono_ldstr (domain, image, ind);
4322 mono_ldsflda (MonoClass *klass, int offset)
4324 MonoDomain *domain = mono_domain_get ();
4328 vt = mono_class_vtable (domain, klass);
4329 addr = (char*)(vt->data) + offset;
4336 MEMCOPY (void *dest, const void *src, size_t n)
4340 printf ("MEMCPY(%p to %p [%d]) ", src, dest, n);
4342 for (i = 0; i < l; i++)
4343 printf ("%02x ", *((guint8 *)src + i));
4346 return memcpy (dest, src, n);
4350 void mono_emit_fast_iconv (MBCGEN_TYPE* s, MBTREE_TYPE* tree)
4353 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 12);
4354 x86_fist_membase (s->code, X86_ESP, 8, TRUE); // rounded value
4355 x86_fst_membase (s->code, X86_ESP, 0, FALSE, FALSE); // float value
4356 x86_fp_int_op_membase (s->code, X86_FSUB, X86_ESP, 8, TRUE);
4357 x86_fst_membase (s->code, X86_ESP, 4, FALSE, TRUE); // diff
4359 x86_pop_reg (s->code, tree->reg1); // float value
4360 x86_test_reg_reg (s->code, tree->reg1, tree->reg1);
4361 br[0] = s->code; x86_branch8 (s->code, X86_CC_S, 0, TRUE);
4363 x86_pop_reg (s->code, tree->reg1); // diff
4364 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->reg1);
4365 x86_pop_reg (s->code, tree->reg1); // rounded value
4366 x86_alu_reg_imm (s->code, X86_SBB, tree->reg1, 0);
4367 br[1] = s->code; x86_jump8 (s->code, 0);
4370 x86_patch (br[0], s->code);
4372 x86_pop_reg (s->code, tree->reg1); // diff
4373 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->reg1);
4374 x86_pop_reg (s->code, tree->reg1); // rounded value
4375 br[2] = s->code; x86_branch8 (s->code, X86_CC_Z, 0, FALSE);
4376 x86_alu_reg_imm (s->code, X86_SBB, tree->reg1, -1);
4377 x86_patch (br[1], s->code);
4378 x86_patch (br[2], s->code);
4381 void mono_emit_fast_iconv_i8 (MBCGEN_TYPE* s, MBTREE_TYPE* tree)
4384 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 16);
4385 x86_fld_reg (s->code, 0);
4386 x86_fist_pop_membase (s->code, X86_ESP, 8, TRUE); // rounded value (qword)
4387 x86_fst_membase (s->code, X86_ESP, 0, FALSE, FALSE); // float value
4388 x86_fild_membase (s->code, X86_ESP, 8, TRUE);
4389 x86_fp_op_reg (s->code, X86_FSUB, 1, TRUE); // diff
4390 x86_fst_membase (s->code, X86_ESP, 4, FALSE, TRUE); // diff
4392 x86_pop_reg (s->code, tree->reg1); // float value
4393 x86_test_reg_reg (s->code, tree->reg1, tree->reg1);
4394 br[0] = s->code; x86_branch8 (s->code, X86_CC_S, 0, TRUE);
4396 x86_pop_reg (s->code, tree->reg1); // diff
4397 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->reg1);
4398 x86_pop_reg (s->code, tree->reg1); // rounded value
4399 x86_pop_reg (s->code, tree->reg2);
4400 x86_alu_reg_imm (s->code, X86_SBB, tree->reg1, 0);
4401 x86_alu_reg_imm (s->code, X86_SBB, tree->reg2, 0);
4402 br[1] = s->code; x86_jump8 (s->code, 0);
4405 x86_patch (br[0], s->code);
4407 x86_pop_reg (s->code, tree->reg1); // diff
4408 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->reg1);
4409 x86_pop_reg (s->code, tree->reg1); // rounded value
4410 x86_pop_reg (s->code, tree->reg2);
4411 br[2] = s->code; x86_branch8 (s->code, X86_CC_Z, 0, FALSE);
4412 x86_alu_reg_imm (s->code, X86_SBB, tree->reg1, -1);
4413 x86_alu_reg_imm (s->code, X86_SBB, tree->reg2, -1);
4414 x86_patch (br[1], s->code);
4415 x86_patch (br[2], s->code);