2 * x86.brg: X86 code generator
5 * Dietmar Maurer (dietmar@ximian.com)
7 * (C) 2001 Ximian, Inc.
14 #include <sys/syscall.h>
16 #include <mono/metadata/blob.h>
17 #include <mono/metadata/metadata.h>
18 #include <mono/metadata/loader.h>
19 #include <mono/metadata/object.h>
20 #include <mono/metadata/tabledefs.h>
21 #include <mono/arch/x86/x86-codegen.h>
27 #define MBTREE_TYPE MBTree
28 #define MBCGEN_TYPE MonoFlowGraph
29 #define MBCOST_DATA MonoFlowGraph
30 #define MBALLOC_STATE mono_mempool_alloc (data->mp, sizeof (MBState))
33 AMImmediate = 0, // ptr
35 AMIndex = 2, // V[REG*X]
36 AMBaseIndex = 3, // V[REG*X][REG]
57 unsigned last_instr:1;
79 gint64 mono_llmult (gint64 a, gint64 b);
80 gint64 mono_lldiv (gint64 a, gint64 b);
81 gint64 mono_llrem (gint64 a, gint64 b);
82 guint64 mono_lldiv_un (guint64 a, guint64 b);
83 guint64 mono_llrem_un (guint64 a, guint64 b);
86 get_throw_exception (void);
89 get_mono_object_isinst (void);
91 #define MB_OPT_LEVEL 1
94 #define MB_USE_OPT1(c) 65535
95 #define MB_USE_OPT2(c) 65535
98 #define MB_USE_OPT1(c) c
99 #define MB_USE_OPT2(c) 65535
101 #if MB_OPT_LEVEL >= 2
102 #define MB_USE_OPT1(c) c
103 #define MB_USE_OPT2(c) c
109 #define MEMCOPY debug_memcpy
110 void *MEMCOPY (void *dest, const void *src, size_t n);
112 #define PRINT_REG(text,reg) \
113 g_assert (reg >= 0); \
114 x86_push_reg (s->code, X86_EAX); \
115 x86_push_reg (s->code, X86_EDX); \
116 x86_push_reg (s->code, X86_ECX); \
117 x86_push_reg (s->code, reg); \
118 x86_push_imm (s->code, reg); \
119 x86_push_imm (s->code, text " %d %p\n"); \
120 x86_call_code (s->code, printf); \
121 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 3*4); \
122 x86_pop_reg (s->code, X86_ECX); \
123 x86_pop_reg (s->code, X86_EDX); \
124 x86_pop_reg (s->code, X86_EAX);
127 #define MEMCOPY memcpy
129 #define PRINT_REG(x,y)
133 /* The call instruction for virtual functions must have a known
134 * size (used by x86_magic_trampoline)
136 #define x86_call_virtual(inst,basereg,disp) \
138 *(inst)++ = (unsigned char)0xff; \
139 x86_address_byte ((inst), 2, 2, (basereg)); \
140 x86_imm_emit32 ((inst), (disp)); \
146 # terminal definitions
150 %term CONST_I4 CONST_I8 CONST_R4 CONST_R8
151 %term LDIND_I1 LDIND_U1 LDIND_I2 LDIND_U2 LDIND_I4 LDIND_I8 LDIND_R4 LDIND_R8
152 %term LDIND_U4 LDIND_OBJ
153 %term STIND_I1 STIND_I2 STIND_I4 STIND_I8 STIND_R4 STIND_R8 STIND_OBJ
154 %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
155 %term BREAK SWITCH BR RET RETV ENDFINALLY
156 %term ADD SUB MUL DIV DIV_UN REM REM_UN AND OR XOR SHL SHR SHR_UN NEG NOT
157 %term BLT BLT_UN BEQ BNE_UN BRTRUE BRFALSE BGE BGE_UN BLE BLE_UN BGT BGT_UN
159 %term CONV_I4 CONV_I1 CONV_I2 CONV_I8 CONV_U8 CONV_R4 CONV_R8
160 %term CONV_OVF_U4 CONV_OVF_I2 CONV_OVF_U2 CONV_OVF_U8
161 %term INTF_ADDR VFUNC_ADDR NOP NEWARR NEWOBJ CPOBJ POP INITOBJ VTYPE ISINST CASTCLASS
162 %term EXCEPTION THROW RETHROW HANDLER
179 tree->data.ainfo.offset = tree->data.i;
180 tree->data.ainfo.amode = AMImmediate;
184 tree->data.ainfo.offset = tree->data.i;
185 tree->data.ainfo.amode = AMImmediate;
188 acon: ADD (ADDR_G, CONST_I4) {
189 tree->data.ainfo.offset = (unsigned)tree->left->data.p + tree->right->data.i;
190 tree->data.ainfo.amode = AMImmediate;
196 tree->data.ainfo.offset = 0;
197 tree->data.ainfo.basereg = tree->reg1;
198 tree->data.ainfo.amode = AMBase;
201 base: ADD (reg, acon) {
202 tree->data.ainfo.offset = tree->right->data.i;
203 tree->data.ainfo.basereg = tree->left->reg1;
204 tree->data.ainfo.amode = AMBase;
208 tree->data.ainfo.offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
209 tree->data.ainfo.basereg = X86_EBP;
210 tree->data.ainfo.amode = AMBase;
214 tree->data.ainfo.offset = 0;
215 tree->data.ainfo.indexreg = tree->reg1;
216 tree->data.ainfo.shift = 0;
217 tree->data.ainfo.amode = AMIndex;
220 index: SHL (reg, CONST_I4) {
221 tree->data.ainfo.offset = 0;
222 tree->data.ainfo.amode = AMIndex;
223 tree->data.ainfo.indexreg = tree->left->reg1;
224 tree->data.ainfo.shift = tree->right->data.i;
226 MBCOND (tree->right->data.i == 0 ||
227 tree->right->data.i == 1 ||
228 tree->right->data.i == 2 ||
229 tree->right->data.i == 3);
234 index: MUL (reg, CONST_I4) {
235 static int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
237 tree->data.ainfo.offset = 0;
238 tree->data.ainfo.amode = AMIndex;
239 tree->data.ainfo.indexreg = tree->left->reg1;
240 tree->data.ainfo.shift = fast_log2 [tree->right->data.i];
242 MBCOND (tree->right->data.i == 1 ||
243 tree->right->data.i == 2 ||
244 tree->right->data.i == 4 ||
245 tree->right->data.i == 8);
254 addr: ADD (index, base) {
255 tree->data.ainfo.offset = tree->right->data.ainfo.offset;
256 tree->data.ainfo.basereg = tree->right->data.ainfo.basereg;
257 tree->data.ainfo.amode = tree->left->data.ainfo.amode |
258 tree->right->data.ainfo.amode;
259 tree->data.ainfo.shift = tree->left->data.ainfo.shift;
260 tree->data.ainfo.indexreg = tree->left->data.ainfo.indexreg;
263 # we pass exception in ECX to catch handler
265 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
267 if (tree->reg1 != X86_ECX)
268 x86_mov_reg_reg (s->code, tree->reg1, X86_ECX, 4);
270 /* store it so that we can RETHROW it later */
271 x86_mov_membase_reg (s->code, X86_EBP, offset, tree->reg1, 4);
275 if (tree->left->reg1 != X86_ECX)
276 x86_mov_reg_reg (s->code, X86_ECX, tree->left->reg1, 4);
278 x86_call_code (s->code, get_throw_exception ());
282 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
284 x86_mov_reg_membase (s->code, X86_ECX, X86_EBP, offset, 4);
286 x86_call_code (s->code, get_throw_exception ());
290 gint32 addr = tree->data.bb->addr - tree->addr - 5;
292 x86_call_imm (s->code, addr);
299 stmt: STIND_I4 (addr, reg) {
300 PRINT_REG ("STIND_I4", tree->right->reg1);
302 switch (tree->left->data.ainfo.amode) {
305 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
309 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
310 tree->left->data.ainfo.offset, tree->right->reg1, 4);
313 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
314 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
315 tree->right->reg1, 4);
318 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
319 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
320 tree->right->reg1, 4);
325 stmt: STIND_I1 (addr, reg) {
326 PRINT_REG ("STIND_I1", tree->right->reg1);
328 switch (tree->left->data.ainfo.amode) {
331 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 1);
335 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
336 tree->left->data.ainfo.offset, tree->right->reg1, 1);
339 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
340 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
341 tree->right->reg1, 1);
344 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
345 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
346 tree->right->reg1, 1);
351 stmt: STIND_I2 (addr, reg) {
352 PRINT_REG ("STIND_I2", tree->right->reg1);
354 switch (tree->left->data.ainfo.amode) {
357 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 2);
361 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
362 tree->left->data.ainfo.offset, tree->right->reg1, 2);
365 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
366 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
367 tree->right->reg1, 2);
370 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
371 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
372 tree->right->reg1, 2);
377 reg: LDIND_I4 (addr) {
379 switch (tree->left->data.ainfo.amode) {
382 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
386 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
387 tree->left->data.ainfo.offset, 4);
390 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
391 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
394 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
395 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
396 tree->left->data.ainfo.shift, 4);
401 PRINT_REG ("LDIND_I4", tree->reg1);
404 reg: LDIND_I1 (addr) {
405 switch (tree->left->data.ainfo.amode) {
408 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, FALSE);
412 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
413 tree->left->data.ainfo.offset, TRUE, FALSE);
416 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
417 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, TRUE, FALSE);
420 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
421 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
422 tree->left->data.ainfo.shift, TRUE, FALSE);
426 PRINT_REG ("LDIND_I1", tree->reg1);
429 reg: LDIND_U1 (addr) {
430 switch (tree->left->data.ainfo.amode) {
433 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, FALSE);
437 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
438 tree->left->data.ainfo.offset, FALSE, FALSE);
441 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
442 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, FALSE, FALSE);
445 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
446 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
447 tree->left->data.ainfo.shift, FALSE, FALSE);
451 PRINT_REG ("LDIND_U1", tree->reg1);
454 reg: LDIND_I2 (addr) {
455 switch (tree->left->data.ainfo.amode) {
458 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, TRUE);
462 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
463 tree->left->data.ainfo.offset, TRUE, TRUE);
466 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
467 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, TRUE, TRUE);
470 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
471 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
472 tree->left->data.ainfo.shift, TRUE, TRUE);
476 PRINT_REG ("LDIND_U2", tree->reg1);
479 reg: LDIND_U2 (addr) {
480 switch (tree->left->data.ainfo.amode) {
483 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, TRUE);
487 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
488 tree->left->data.ainfo.offset, FALSE, TRUE);
491 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
492 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, FALSE, TRUE);
495 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
496 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
497 tree->left->data.ainfo.shift, FALSE, TRUE);
501 PRINT_REG ("LDIND_U2", tree->reg1);
504 reg: LDIND_U4 (addr) {
505 switch (tree->left->data.ainfo.amode) {
508 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
512 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
513 tree->left->data.ainfo.offset, 4);
516 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
517 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
520 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
521 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
522 tree->left->data.ainfo.shift, 4);
526 PRINT_REG ("LDIND_U4", tree->reg1);
530 tree->data.i = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
534 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
535 x86_lea_membase (s->code, tree->reg1, X86_EBP, offset);
540 x86_mov_reg_imm (s->code, tree->reg1, tree->data.p);
544 if (tree->reg1 != tree->left->reg1)
545 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
546 x86_alu_reg_imm (s->code, X86_AND, tree->reg1, 0xff);
550 if (tree->reg1 != tree->left->reg1)
551 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
552 x86_alu_reg_imm (s->code, X86_AND, tree->reg1, 0xffff);
556 x86_mov_reg_imm (s->code, tree->reg1, tree->data.i);
560 if (tree->reg1 != tree->left->reg1)
561 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
562 PRINT_REG ("CONV_I4", tree->left->reg1);
565 reg: CONV_OVF_U4 (reg) {
566 x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
567 x86_branch8 (s->code, X86_CC_EQ, 10, TRUE);
568 x86_mov_reg_imm (s->code, X86_ECX, get_exception_overflow ());
569 x86_call_code (s->code, get_throw_exception ());
570 if (tree->reg1 != tree->left->reg1)
571 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
574 reg: CONV_OVF_I2 (reg) {
575 /* Probe value to be within -32768 and 32767 */
577 x86_alu_reg_imm (s->code, X86_CMP, tree->reg1, 32767);
578 x86_branch8 (s->code, X86_CC_LE, 10, TRUE);
579 x86_mov_reg_imm (s->code, X86_ECX, get_exception_overflow ());
580 x86_call_code (s->code, get_throw_exception ());
582 x86_alu_reg_imm (s->code, X86_CMP, tree->reg1, -32768);
583 x86_branch8 (s->code, X86_CC_LT, -17, TRUE);
584 if (tree->reg1 != tree->left->reg1)
585 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
588 reg: CONV_OVF_U2 (reg) {
589 /* Probe value to be within 0 and 65535 */
590 x86_test_reg_imm (s->code, tree->left->reg1, 0xffff0000);
591 x86_branch8 (s->code, X86_CC_EQ, 10, TRUE);
592 x86_mov_reg_imm (s->code, X86_ECX, get_exception_overflow ());
593 x86_call_code (s->code, get_throw_exception ());
594 if (tree->reg1 != tree->left->reg1)
595 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
598 reg: MUL (reg, reg) {
599 if (tree->reg1 != tree->left->reg1)
600 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
601 x86_imul_reg_reg (s->code, tree->reg1, tree->right->reg1);
604 reg: DIV (reg, reg) {
605 if (tree->left->reg1 != X86_EAX)
606 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
609 x86_div_reg (s->code, tree->right->reg1, TRUE);
611 g_assert (tree->reg1 == X86_EAX &&
612 tree->reg2 == X86_EDX);
615 reg: DIV_UN (reg, reg) {
616 if (tree->left->reg1 != X86_EAX)
617 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
620 x86_div_reg (s->code, tree->right->reg1, FALSE);
622 g_assert (tree->reg1 == X86_EAX &&
623 tree->reg2 == X86_EDX);
626 reg: REM (reg, reg) {
627 if (tree->left->reg1 != X86_EAX)
628 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
631 x86_div_reg (s->code, tree->right->reg1, TRUE);
632 x86_mov_reg_reg (s->code, X86_EAX, X86_EDX, 4);
634 g_assert (tree->reg1 == X86_EAX &&
635 tree->reg2 == X86_EDX);
638 reg: REM_UN (reg, reg) {
639 if (tree->left->reg1 != X86_EAX)
640 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
643 x86_div_reg (s->code, tree->right->reg1, FALSE);
644 x86_mov_reg_reg (s->code, X86_EAX, X86_EDX, 4);
646 g_assert (tree->reg1 == X86_EAX &&
647 tree->reg2 == X86_EDX);
650 reg: ADD (reg, CONST_I4) "MB_USE_OPT1(0)" {
651 if (tree->reg1 != tree->left->reg1)
652 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
653 x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, tree->right->data.i);
656 reg: ADD (reg, reg) {
657 if (tree->reg1 != tree->left->reg1)
658 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
659 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
662 reg: SUB (reg, CONST_I4) "MB_USE_OPT1(0)" {
663 if (tree->reg1 != tree->left->reg1)
664 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
665 x86_alu_reg_imm (s->code, X86_SUB, tree->reg1, tree->right->data.i);
668 reg: SUB (reg, reg) {
669 if (tree->reg1 != tree->left->reg1)
670 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
671 x86_alu_reg_reg (s->code, X86_SUB, tree->reg1, tree->right->reg1);
674 reg: CEQ (reg, reg) {
675 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
676 x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
677 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
680 reg: CLT (reg, reg) {
681 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
682 x86_set_reg (s->code, X86_CC_LT, tree->reg1, TRUE);
683 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
686 reg: AND (reg, reg) {
687 if (tree->reg1 != tree->left->reg1)
688 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
689 x86_alu_reg_reg (s->code, X86_AND, tree->reg1, tree->right->reg1);
693 if (tree->reg1 != tree->left->reg1)
694 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
695 x86_alu_reg_reg (s->code, X86_OR, tree->reg1, tree->right->reg1);
698 reg: XOR (reg, reg) {
699 if (tree->reg1 != tree->left->reg1)
700 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
701 x86_alu_reg_reg (s->code, X86_XOR, tree->reg1, tree->right->reg1);
705 if (tree->reg1 != tree->left->reg1)
706 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
707 x86_neg_reg (s->code, tree->reg1);
711 if (tree->reg1 != tree->left->reg1)
712 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
713 x86_not_reg (s->code, tree->reg1);
716 reg: SHL (reg, CONST_I4) {
717 if (tree->reg1 != tree->left->reg1)
718 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
719 x86_shift_reg_imm (s->code, X86_SHL, tree->reg1, tree->right->data.i);
722 reg: SHL (reg, reg) {
723 if (tree->reg1 != tree->left->reg1)
724 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
725 if (tree->right->reg1 != X86_ECX)
726 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
727 x86_shift_reg (s->code, X86_SHL, tree->reg1);
729 g_assert (tree->reg1 != X86_ECX &&
730 tree->left->reg1 != X86_ECX);
733 reg: SHR (reg, CONST_I4) {
734 if (tree->reg1 != tree->left->reg1)
735 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
736 x86_shift_reg_imm (s->code, X86_SAR, tree->reg1, tree->right->data.i);
739 reg: SHR (reg, reg) {
740 if (tree->reg1 != tree->left->reg1)
741 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
742 if (tree->right->reg1 != X86_ECX)
743 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
744 x86_shift_reg (s->code, X86_SAR, tree->reg1);
746 g_assert (tree->reg1 != X86_ECX &&
747 tree->left->reg1 != X86_ECX);
750 reg: SHR_UN (reg, CONST_I4) {
751 if (tree->reg1 != tree->left->reg1)
752 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
753 x86_shift_reg_imm (s->code, X86_SHR, tree->reg1, tree->right->data.i);
756 reg: SHR_UN (reg, reg) {
757 if (tree->reg1 != tree->left->reg1)
758 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
759 if (tree->right->reg1 != X86_ECX)
760 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
761 x86_shift_reg (s->code, X86_SHR, tree->reg1);
763 g_assert (tree->reg1 != X86_ECX &&
764 tree->left->reg1 != X86_ECX);
769 x86_mov_reg_membase (s->code, tree->reg1, tree->left->reg1,
770 G_STRUCT_OFFSET (MonoArray, bounds), 4);
771 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1,
772 G_STRUCT_OFFSET (MonoArrayBounds, length), 4);
775 #reg: LDELEMA (reg, reg) {
776 # x86_imul_reg_reg_imm (s->code, tree->right->reg1, tree->right->reg1, tree->data.i);
777 # x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
778 # x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, G_STRUCT_OFFSET (MonoArray, vector));
782 if (tree->reg1 != X86_EAX)
783 x86_push_reg (s->code, X86_EAX);
784 x86_push_reg (s->code, X86_ECX);
785 x86_push_reg (s->code, X86_EDX);
787 x86_push_reg (s->code, tree->left->reg1);
788 x86_push_imm (s->code, tree->data.p);
789 x86_call_code (s->code, mono_array_new);
790 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer) + 4);
792 x86_pop_reg (s->code, X86_EDX);
793 x86_pop_reg (s->code, X86_ECX);
794 if (tree->reg1 != X86_EAX) {
795 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
796 x86_pop_reg (s->code, X86_EAX);
801 if (tree->reg1 != X86_EAX)
802 x86_push_reg (s->code, X86_EAX);
803 x86_push_reg (s->code, X86_ECX);
804 x86_push_reg (s->code, X86_EDX);
806 x86_push_imm (s->code, tree->data.p);
807 x86_call_code (s->code, mono_object_new);
808 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
810 x86_pop_reg (s->code, X86_EDX);
811 x86_pop_reg (s->code, X86_ECX);
812 if (tree->reg1 != X86_EAX) {
813 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
814 x86_pop_reg (s->code, X86_EAX);
818 reg: CASTCLASS (reg) {
819 guint8 *start = s->code, *l1, *l2, *l3, *l4, *le;
822 tree->is_jump = TRUE;
823 l1 = l2 = l3 = l4 = le = NULL;
825 for (i = 0; i < 2; i++) {
828 if (tree->reg1 != X86_EAX)
829 x86_push_reg (s->code, X86_EAX);
831 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
832 x86_branch8 (s->code, X86_CC_EQ, le - l2, FALSE);
834 x86_push_reg (s->code, X86_ECX);
835 x86_push_reg (s->code, X86_EDX);
837 x86_push_imm (s->code, tree->data.klass);
838 x86_push_reg (s->code, tree->left->reg1);
839 x86_call_code (s->code, mono_object_isinst);
840 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
841 x86_pop_reg (s->code, X86_EDX);
842 x86_pop_reg (s->code, X86_ECX);
844 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0);
845 x86_branch8 (s->code, X86_CC_NE, le - l3, FALSE);
848 x86_mov_reg_imm (s->code, X86_ECX, get_exception_invalid_cast ());
849 x86_call_code (s->code, get_throw_exception ());
857 if (tree->reg1 != X86_EAX)
858 x86_push_reg (s->code, X86_EAX);
859 x86_push_reg (s->code, X86_ECX);
860 x86_push_reg (s->code, X86_EDX);
862 x86_push_imm (s->code, tree->data.klass);
863 x86_push_reg (s->code, tree->left->reg1);
864 x86_call_code (s->code, mono_object_isinst);
865 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
867 x86_pop_reg (s->code, X86_EDX);
868 x86_pop_reg (s->code, X86_ECX);
869 if (tree->reg1 != X86_EAX) {
870 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
871 x86_pop_reg (s->code, X86_EAX);
877 # guint8 *start = s->code, *l1, *l2, *l3, *l4, *le;
878 # MonoClass *k = tree->data.klass;
879 # int treg = tree->reg1;
882 # tree->is_jump = TRUE;
883 # l1 = l2 = l3 = l4 = le = NULL;
885 # for (i = 0; i < 2; i++) {
888 # x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
889 # x86_branch8 (s->code, X86_CC_EQ, le - l1, FALSE);
892 # x86_push_reg (s->code, tree->left->reg1);
894 # if (k->flags & TYPE_ATTRIBUTE_INTERFACE) {
895 # x86_mov_reg_membase (s->code, treg, treg, 0, 4); // treg = o->klass
896 # x86_mov_reg_membase (s->code, treg, treg, G_STRUCT_OFFSET (MonoClass, max_interface_id), 4);
897 # x86_alu_reg_imm (s->code, X86_CMP, treg, k->interface_id);
898 # x86_branch8 (s->code, X86_CC_GE, l3 - l2, FALSE);
900 # x86_pop_reg (s->code, treg);
901 # x86_alu_reg_reg (s->code, X86_XOR, treg, treg);
902 # x86_jump8 (s->code, le - l3);
904 # x86_mov_reg_membase (s->code, treg, X86_ESP, 0, 4); // treg = o
905 # x86_mov_reg_membase (s->code, treg, treg, 0, 4); // treg = o->klass
906 # x86_mov_reg_membase (s->code, treg, treg, G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
907 # x86_mov_reg_membase (s->code, treg, treg, (k->interface_id << 2), 4);
908 # x86_alu_reg_imm (s->code, X86_CMP, treg, 0);
909 # x86_pop_reg (s->code, treg);
910 # x86_branch8 (s->code, X86_CC_NE, le - l4, FALSE);
912 # x86_alu_reg_reg (s->code, X86_XOR, treg, treg);
914 # x86_mov_reg_membase (s->code, treg, treg, 0, 4); // treg = o->klass
915 # x86_mov_reg_membase (s->code, treg, treg, G_STRUCT_OFFSET (MonoClass, baseval), 4);
916 # x86_alu_reg_imm (s->code, X86_SUB, treg, k->baseval);
917 # x86_alu_reg_imm (s->code, X86_CMP, treg, k->diffval);
918 # x86_pop_reg (s->code, treg);
919 # x86_branch8 (s->code, X86_CC_LE, le - l2, FALSE);
921 # x86_alu_reg_reg (s->code, X86_XOR, treg, treg);
925 # //x86_breakpoint (s->code);
929 stmt: INITOBJ (reg) {
934 if (i == 1 || i == 2 || i == 4) {
937 if (tree->left->reg1 != X86_EAX)
940 x86_push_reg (s->code, t);
941 x86_alu_reg_reg (s->code, X86_XOR, t, t);
943 switch (tree->data.i) {
945 x86_mov_regp_reg (s->code, tree->left->reg1, t, 4);
948 x86_mov_regp_reg (s->code, tree->left->reg1, t, 4);
951 x86_mov_regp_reg (s->code, tree->left->reg1, t, 4);
954 x86_pop_reg (s->code, t);
959 i = tree->data.i / 4;
960 j = tree->data.i % 4;
962 x86_push_reg (s->code, X86_EAX);
964 if (tree->left->reg1 != X86_EDI) {
965 x86_push_reg (s->code, X86_EDI);
966 x86_mov_reg_reg (s->code, X86_EDI, tree->left->reg1, 4);
970 x86_push_reg (s->code, X86_ECX);
971 x86_alu_reg_reg (s->code, X86_XOR, X86_EAX, X86_EAX);
972 x86_mov_reg_imm (s->code, X86_ECX, i);
974 x86_prefix (s->code, X86_REP_PREFIX);
976 x86_pop_reg (s->code, X86_ECX);
980 for (i = 0; i < j; i++)
983 if (tree->left->reg1 != X86_EDI)
984 x86_pop_reg (s->code, X86_EDI);
986 x86_pop_reg (s->code, X86_EAX);
993 stmt: STIND_I4 (reg, CONST_I4) "MB_USE_OPT1(0)" {
994 x86_mov_membase_imm (s->code, tree->left->reg1, 0,
995 tree->right->data.i, 4);
998 stmt: STIND_I4 (reg, reg) {
999 x86_mov_membase_reg (s->code, tree->left->reg1, 0,
1000 tree->right->reg1, 4);
1003 stmt: STIND_I4 (locaddr, CONST_I4) "MB_USE_OPT1(0)" {
1004 x86_mov_membase_imm (s->code, X86_EBP, tree->left->data.i,
1005 tree->right->data.i, 4);
1008 stmt: STIND_I1 (locaddr, reg) {
1009 x86_mov_membase_reg (s->code, X86_EBP, tree->left->data.i,
1010 tree->right->reg1, 1);
1013 stmt: STIND_I2 (locaddr, reg) {
1014 x86_mov_membase_reg (s->code, X86_EBP, tree->left->data.i,
1015 tree->right->reg1, 2);
1018 stmt: STIND_I4 (locaddr, reg) {
1019 x86_mov_membase_reg (s->code, X86_EBP, tree->left->data.i,
1020 tree->right->reg1, 4);
1023 stmt: STIND_I4 (ADDR_G, reg) {
1024 x86_mov_mem_reg (s->code, tree->left->data.p,
1025 tree->right->reg1, 4);
1029 gint32 addr = tree->data.bb->addr - tree->addr - 5;
1032 x86_jump32 (s->code, addr);
1035 stmt: BLT (reg, reg) 1 {
1039 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1040 offset = 6 + s->code - s->start;
1041 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - offset, TRUE);
1044 stmt: BLT (reg, CONST_I4) "MB_USE_OPT1(0)" {
1048 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1049 offset = 6 + s->code - s->start;
1050 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - offset, TRUE);
1053 stmt: BLT_UN (reg, reg) 1 {
1057 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1058 offset = 6 + s->code - s->start;
1059 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - offset, FALSE);
1062 stmt: BLT_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1066 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1067 offset = 6 + s->code - s->start;
1068 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - offset, FALSE);
1071 stmt: BGT (reg, reg) 1 {
1075 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1076 offset = 6 + s->code - s->start;
1077 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - offset, TRUE);
1080 stmt: BGT (reg, CONST_I4) "MB_USE_OPT1(0)" {
1084 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1085 offset = 6 + s->code - s->start;
1086 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - offset, TRUE);
1089 stmt: BGT_UN (reg, reg) 1 {
1093 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1094 offset = 6 + s->code - s->start;
1095 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - offset, FALSE);
1098 stmt: BGT_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1102 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1103 offset = 6 + s->code - s->start;
1104 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - offset, FALSE);
1107 stmt: BEQ (reg, CONST_I4) "MB_USE_OPT1(0)" {
1111 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1112 offset = 6 + s->code - s->start;
1113 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, TRUE);
1116 stmt: BEQ (reg, reg) 1 {
1120 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1121 offset = 6 + s->code - s->start;
1122 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, TRUE);
1125 stmt: BNE_UN (reg, reg) 1 {
1129 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1130 offset = 6 + s->code - s->start;
1131 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
1134 stmt: BNE_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1138 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1139 offset = 6 + s->code - s->start;
1140 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
1143 stmt: BGE (reg, reg) 1 {
1147 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1148 offset = 6 + s->code - s->start;
1149 x86_branch32 (s->code, X86_CC_GE, tree->data.bb->addr - offset, TRUE);
1152 stmt: BGE (reg, CONST_I4) "MB_USE_OPT1(0)" {
1156 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1157 offset = 6 + s->code - s->start;
1158 x86_branch32 (s->code, X86_CC_GE, tree->data.bb->addr - offset, TRUE);
1161 stmt: BGE_UN (reg, reg) 1 {
1165 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1166 offset = 6 + s->code - s->start;
1167 x86_branch32 (s->code, X86_CC_GE, tree->data.bb->addr - offset, FALSE);
1170 stmt: BGE_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1174 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1175 offset = 6 + s->code - s->start;
1176 x86_branch32 (s->code, X86_CC_GE, tree->data.bb->addr - offset, FALSE);
1179 stmt: BLE (reg, reg) 1 {
1183 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1184 offset = 6 + s->code - s->start;
1185 x86_branch32 (s->code, X86_CC_LE, tree->data.bb->addr - offset, TRUE);
1188 stmt: BLE (reg, CONST_I4) "MB_USE_OPT1(0)" {
1192 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1193 offset = 6 + s->code - s->start;
1194 x86_branch32 (s->code, X86_CC_LE, tree->data.bb->addr - offset, TRUE);
1197 stmt: BLE_UN (reg, reg) 1 {
1201 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1202 offset = 6 + s->code - s->start;
1203 x86_branch32 (s->code, X86_CC_LE, tree->data.bb->addr - offset, FALSE);
1206 stmt: BLE_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1210 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1211 offset = 6 + s->code - s->start;
1212 x86_branch32 (s->code, X86_CC_LE, tree->data.bb->addr - offset, FALSE);
1215 stmt: BRTRUE (reg) {
1219 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
1220 offset = 6 + s->code - s->start;
1221 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, TRUE);
1224 stmt: BRFALSE (reg) {
1228 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
1229 offset = 6 + s->code - s->start;
1230 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, TRUE);
1234 x86_breakpoint (s->code);
1238 if (tree->left->reg1 != X86_EAX)
1239 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1241 if (!tree->last_instr) {
1243 x86_jump32 (s->code, s->epilog - 5);
1248 if (!tree->last_instr) {
1250 x86_jump32 (s->code, s->epilog - 5);
1254 stmt: ARG_I4 (reg) {
1255 x86_push_reg (s->code, tree->left->reg1);
1258 # fixme: we must free the allocated strings somewhere
1259 stmt: ARG_STRING (reg) {
1260 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
1261 x86_push_reg (s->code, X86_EAX);
1262 x86_push_reg (s->code, X86_ECX);
1263 x86_push_reg (s->code, X86_EDX);
1265 x86_push_reg (s->code, tree->left->reg1);
1266 x86_call_code (s->code, mono_string_to_utf8);
1267 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
1269 x86_mov_membase_reg (s->code, X86_ESP, 12, X86_EAX, 4);
1271 x86_pop_reg (s->code, X86_EDX);
1272 x86_pop_reg (s->code, X86_ECX);
1273 x86_pop_reg (s->code, X86_EAX);
1276 stmt: ARG_I4 (ADDR_G) {
1277 x86_push_imm (s->code, tree->left->data.p);
1280 stmt: ARG_I4 (CONST_I4) "MB_USE_OPT1(0)" {
1281 x86_push_imm (s->code, tree->left->data.i);
1288 reg: CALL_I4 (this, reg) {
1289 MethodCallInfo *ci = tree->data.ci;
1291 int lreg = tree->left->reg1;
1292 int rreg = tree->right->reg1;
1294 if (lreg == treg || rreg == treg)
1296 if (lreg == treg || rreg == treg)
1298 if (lreg == treg || rreg == treg)
1299 g_assert_not_reached ();
1301 if (ci->vtype_num) {
1302 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1303 x86_lea_membase (s->code, treg, X86_EBP, offset);
1304 x86_push_reg (s->code, treg);
1307 if (tree->left->op != MB_TERM_NOP) {
1308 g_assert (lreg >= 0);
1309 x86_push_reg (s->code, lreg);
1312 x86_call_reg (s->code, rreg);
1315 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1317 PRINT_REG ("CALL_I4", tree->reg1);
1319 g_assert (tree->reg1 == X86_EAX);
1322 reg: CALL_I4 (this, LDIND_I4 (ADDR_G)) {
1323 MethodCallInfo *ci = tree->data.ci;
1324 int lreg = tree->left->reg1;
1330 if (ci->vtype_num) {
1331 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1332 x86_lea_membase (s->code, treg, X86_EBP, offset);
1333 x86_push_reg (s->code, treg);
1336 if (tree->left->op != MB_TERM_NOP) {
1337 g_assert (lreg >= 0);
1338 x86_push_reg (s->code, lreg);
1341 x86_call_mem (s->code, tree->right->left->data.p);
1344 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1346 PRINT_REG ("CALL_I4", tree->reg1);
1348 g_assert (tree->reg1 == X86_EAX);
1351 reg: CALL_I4 (this, INTF_ADDR) {
1352 MethodCallInfo *ci = tree->data.ci;
1353 int lreg = tree->left->reg1;
1359 if (ci->vtype_num) {
1360 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1361 x86_lea_membase (s->code, treg, X86_EBP, offset);
1362 x86_push_reg (s->code, treg);
1365 if (tree->left->op != MB_TERM_NOP) {
1366 g_assert (lreg >= 0);
1367 x86_push_reg (s->code, lreg);
1370 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1371 x86_mov_reg_membase (s->code, lreg, lreg,
1372 G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
1373 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
1374 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
1377 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1379 PRINT_REG ("CALL_I4(INTERFACE)", tree->reg1);
1381 g_assert (tree->reg1 == X86_EAX);
1384 reg: CALL_I4 (this, VFUNC_ADDR) {
1385 MethodCallInfo *ci = tree->data.ci;
1386 int lreg = tree->left->reg1;
1392 if (ci->vtype_num) {
1393 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1394 x86_lea_membase (s->code, treg, X86_EBP, offset);
1395 x86_push_reg (s->code, treg);
1398 if (tree->left->op != MB_TERM_NOP) {
1399 g_assert (lreg >= 0);
1400 x86_push_reg (s->code, lreg);
1403 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1404 x86_call_virtual (s->code, lreg,
1405 G_STRUCT_OFFSET (MonoClass, vtable) + (tree->right->data.m->slot << 2));
1408 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1410 PRINT_REG ("CALL_I4(VIRTUAL)", tree->reg1);
1412 g_assert (tree->reg1 == X86_EAX);
1415 stmt: CALL_VOID (this, LDIND_I4 (ADDR_G)) {
1416 MethodCallInfo *ci = tree->data.ci;
1417 int lreg = tree->left->reg1;
1423 if (ci->vtype_num) {
1424 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1425 x86_lea_membase (s->code, treg, X86_EBP, offset);
1426 x86_push_reg (s->code, treg);
1429 if (tree->left->op != MB_TERM_NOP) {
1430 g_assert (lreg >= 0);
1431 x86_push_reg (s->code, lreg);
1434 x86_call_mem (s->code, tree->right->left->data.p);
1437 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1440 stmt: CALL_VOID (this, INTF_ADDR) {
1441 MethodCallInfo *ci = tree->data.ci;
1442 int lreg = tree->left->reg1;
1448 if (ci->vtype_num) {
1449 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1450 x86_lea_membase (s->code, treg, X86_EBP, offset);
1451 x86_push_reg (s->code, treg);
1454 if (tree->left->op != MB_TERM_NOP) {
1455 g_assert (lreg >= 0);
1456 x86_push_reg (s->code, lreg);
1459 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1460 x86_mov_reg_membase (s->code, lreg, lreg,
1461 G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
1462 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
1463 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
1466 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1469 stmt: CALL_VOID (this, VFUNC_ADDR) {
1470 MethodCallInfo *ci = tree->data.ci;
1471 int lreg = tree->left->reg1;
1477 if (ci->vtype_num) {
1478 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1479 x86_lea_membase (s->code, treg, X86_EBP, offset);
1480 x86_push_reg (s->code, treg);
1483 if (tree->left->op != MB_TERM_NOP) {
1484 g_assert (lreg >= 0);
1485 x86_push_reg (s->code, lreg);
1488 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1489 x86_call_virtual (s->code, lreg,
1490 G_STRUCT_OFFSET (MonoClass, vtable) + (tree->right->data.m->slot << 2));
1493 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1496 stmt: SWITCH (reg) {
1498 guint32 *jt = (guint32 *)tree->data.p;
1502 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, jt [0]);
1503 offset = 6 + (guint32)s->code;
1504 x86_branch32 (s->code, X86_CC_GE, jt [jt [0] + 1] - offset, FALSE);
1506 x86_mov_reg_memindex (s->code, X86_EAX, X86_NOBASEREG,
1507 tree->data.i + 4, tree->left->reg1, 2, 4);
1508 x86_jump_reg (s->code, X86_EAX);
1515 reg: CONV_I4 (lreg) {
1516 if (tree->reg1 != tree->left->reg1)
1517 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1523 x86_mov_reg_imm (s->code, tree->reg1, tree->data.i);
1524 x86_mov_reg_imm (s->code, tree->reg2, *(gint32 *)(&tree->data.p + 4));
1527 lreg: CONV_I8 (CONST_I4) {
1528 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
1530 if (tree->left->data.i >= 0)
1531 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1533 x86_mov_reg_imm (s->code, tree->reg2, -1);
1536 lreg: CONV_I8 (reg) {
1539 if (tree->reg1 != tree->left->reg1)
1540 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1542 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
1543 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1544 x86_branch8 (s->code, X86_CC_GE, 5, TRUE);
1546 x86_mov_reg_imm (s->code, tree->reg2, -1);
1547 g_assert ((s->code - i1) == 5);
1550 lreg: CONV_U8 (CONST_I4) 1 {
1551 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
1552 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1555 lreg: CONV_OVF_U8 (CONST_I4) {
1556 if (tree->left->data.i < 0){
1557 x86_mov_reg_imm (s->code, X86_ECX, get_exception_overflow ());
1558 x86_call_code (s->code, get_throw_exception ());
1560 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
1561 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1565 lreg: CONV_OVF_U8 (reg) {
1567 * Buggy: notice that this assumes reg is an int, maybe I should
1568 * generate a CONV_I8 node when the value on the stack is an int?
1570 x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
1571 x86_branch8 (s->code, X86_CC_EQ, 10, TRUE);
1572 x86_mov_reg_imm (s->code, X86_ECX, get_exception_overflow ());
1573 x86_call_code (s->code, get_throw_exception ());
1575 if (tree->reg1 != tree->left->reg1)
1576 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1577 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1580 stmt: STIND_I8 (locaddr, lreg) {
1581 x86_mov_membase_reg (s->code, X86_EBP, tree->left->data.i,
1582 tree->right->reg1, 4);
1583 x86_mov_membase_reg (s->code, X86_EBP, tree->left->data.i + 4,
1584 tree->right->reg2, 4);
1586 stmt: STIND_I8 (addr, lreg) {
1588 switch (tree->left->data.ainfo.amode) {
1591 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
1592 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset + 4, tree->right->reg2, 4);
1596 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
1597 tree->left->data.ainfo.offset, tree->right->reg1, 4);
1598 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
1599 tree->left->data.ainfo.offset + 4, tree->right->reg2, 4);
1602 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
1603 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
1604 tree->right->reg1, 4);
1605 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset + 4,
1606 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
1607 tree->right->reg2, 4);
1610 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
1611 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
1612 tree->right->reg1, 4);
1613 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset + 4,
1614 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
1615 tree->right->reg2, 4);
1620 lreg: LDIND_I8 (locaddr) {
1621 x86_mov_reg_membase (s->code, tree->reg1, X86_EBP,
1622 tree->left->data.i, 4);
1623 x86_mov_reg_membase (s->code, tree->reg2, X86_EBP,
1624 tree->left->data.i + 4, 4);
1627 lreg: LDIND_I8 (addr) {
1628 switch (tree->left->data.ainfo.amode) {
1631 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
1632 x86_mov_reg_mem (s->code, tree->reg2, tree->left->data.ainfo.offset + 4, 4);
1636 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
1637 tree->left->data.ainfo.offset, 4);
1638 x86_mov_reg_membase (s->code, tree->reg2, tree->left->data.ainfo.basereg,
1639 tree->left->data.ainfo.offset + 4, 4);
1642 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
1643 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
1644 x86_mov_reg_memindex (s->code, tree->reg2, X86_NOBASEREG, tree->left->data.ainfo.offset + 4,
1645 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
1648 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
1649 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
1650 tree->left->data.ainfo.shift, 4);
1651 x86_mov_reg_memindex (s->code, tree->reg2, tree->left->data.ainfo.basereg,
1652 tree->left->data.ainfo.offset + 4, tree->left->data.ainfo.indexreg,
1653 tree->left->data.ainfo.shift, 4);
1658 lreg: ADD (lreg, lreg) {
1659 if (tree->reg1 != tree->left->reg1)
1660 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1661 if (tree->reg2 != tree->left->reg2)
1662 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
1663 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
1664 x86_alu_reg_reg (s->code, X86_ADC, tree->reg2, tree->right->reg2);
1667 lreg: SUB (lreg, lreg) {
1668 if (tree->reg1 != tree->left->reg1)
1669 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1670 if (tree->reg2 != tree->left->reg2)
1671 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
1672 x86_alu_reg_reg (s->code, X86_SUB, tree->reg1, tree->right->reg1);
1673 x86_alu_reg_reg (s->code, X86_SUB, tree->reg2, tree->right->reg2);
1676 lreg: AND (lreg, lreg) {
1677 if (tree->reg1 != tree->left->reg1)
1678 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1679 if (tree->reg2 != tree->left->reg2)
1680 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
1681 x86_alu_reg_reg (s->code, X86_AND, tree->reg1, tree->right->reg1);
1682 x86_alu_reg_reg (s->code, X86_AND, tree->reg2, tree->right->reg2);
1685 lreg: OR (lreg, lreg) {
1686 if (tree->reg1 != tree->left->reg1)
1687 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1688 if (tree->reg2 != tree->left->reg2)
1689 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
1690 x86_alu_reg_reg (s->code, X86_OR, tree->reg1, tree->right->reg1);
1691 x86_alu_reg_reg (s->code, X86_OR, tree->reg2, tree->right->reg2);
1695 if (tree->reg1 != tree->left->reg1)
1696 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1697 if (tree->reg2 != tree->left->reg2)
1698 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
1699 x86_neg_reg (s->code, tree->reg1);
1700 x86_alu_reg_imm (s->code, X86_ADC, tree->reg2, 0);
1701 x86_neg_reg (s->code, tree->reg2);
1705 if (tree->reg1 != tree->left->reg1)
1706 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1707 if (tree->reg2 != tree->left->reg2)
1708 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
1709 x86_not_reg (s->code, tree->reg1);
1710 x86_not_reg (s->code, tree->reg2);
1713 lreg: MUL (lreg, lreg) {
1714 if (mono_regset_reg_used (s->rs, X86_ECX))
1715 x86_push_reg (s->code, X86_ECX);
1717 x86_push_reg (s->code, tree->right->reg2);
1718 x86_push_reg (s->code, tree->right->reg1);
1719 x86_push_reg (s->code, tree->left->reg2);
1720 x86_push_reg (s->code, tree->left->reg1);
1721 x86_call_code (s->code, mono_llmult);
1722 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
1724 if (mono_regset_reg_used (s->rs, X86_ECX))
1725 x86_pop_reg (s->code, X86_ECX);
1728 lreg: DIV (lreg, lreg) {
1729 if (mono_regset_reg_used (s->rs, X86_ECX))
1730 x86_push_reg (s->code, X86_ECX);
1732 x86_push_reg (s->code, tree->right->reg2);
1733 x86_push_reg (s->code, tree->right->reg1);
1734 x86_push_reg (s->code, tree->left->reg2);
1735 x86_push_reg (s->code, tree->left->reg1);
1736 x86_call_code (s->code, mono_lldiv);
1737 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
1739 if (mono_regset_reg_used (s->rs, X86_ECX))
1740 x86_pop_reg (s->code, X86_ECX);
1743 lreg: REM (lreg, lreg) {
1744 if (mono_regset_reg_used (s->rs, X86_ECX))
1745 x86_push_reg (s->code, X86_ECX);
1747 x86_push_reg (s->code, tree->right->reg2);
1748 x86_push_reg (s->code, tree->right->reg1);
1749 x86_push_reg (s->code, tree->left->reg2);
1750 x86_push_reg (s->code, tree->left->reg1);
1751 x86_call_code (s->code, mono_llrem);
1752 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
1754 if (mono_regset_reg_used (s->rs, X86_ECX))
1755 x86_pop_reg (s->code, X86_ECX);
1758 lreg: DIV_UN (lreg, lreg) {
1759 if (mono_regset_reg_used (s->rs, X86_ECX))
1760 x86_push_reg (s->code, X86_ECX);
1762 x86_push_reg (s->code, tree->right->reg2);
1763 x86_push_reg (s->code, tree->right->reg1);
1764 x86_push_reg (s->code, tree->left->reg2);
1765 x86_push_reg (s->code, tree->left->reg1);
1766 x86_call_code (s->code, mono_lldiv_un);
1767 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
1769 if (mono_regset_reg_used (s->rs, X86_ECX))
1770 x86_pop_reg (s->code, X86_ECX);
1773 lreg: REM_UN (lreg, lreg) {
1774 if (mono_regset_reg_used (s->rs, X86_ECX))
1775 x86_push_reg (s->code, X86_ECX);
1777 x86_push_reg (s->code, tree->right->reg2);
1778 x86_push_reg (s->code, tree->right->reg1);
1779 x86_push_reg (s->code, tree->left->reg2);
1780 x86_push_reg (s->code, tree->left->reg1);
1781 x86_call_code (s->code, mono_llrem_un);
1782 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
1784 if (mono_regset_reg_used (s->rs, X86_ECX))
1785 x86_pop_reg (s->code, X86_ECX);
1788 lreg: CALL_I8 (this, LDIND_I4 (ADDR_G)) {
1789 MethodCallInfo *ci = tree->data.ci;
1790 int lreg = tree->left->reg1;
1796 if (ci->vtype_num) {
1797 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1798 x86_lea_membase (s->code, treg, X86_EBP, offset);
1799 x86_push_reg (s->code, treg);
1802 if (tree->left->op != MB_TERM_NOP) {
1803 g_assert (lreg >= 0);
1804 x86_push_reg (s->code, lreg);
1807 x86_call_mem (s->code, tree->right->left->data.p);
1810 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1812 g_assert (tree->reg1 == X86_EAX);
1813 g_assert (tree->reg2 == X86_EDX);
1817 if (tree->left->reg1 != X86_EAX) {
1818 if (tree->left->reg2 != X86_EAX) {
1819 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1820 if (tree->left->reg2 != X86_EDX)
1821 x86_mov_reg_reg (s->code, X86_EDX, tree->left->reg2, 4);
1823 x86_mov_reg_reg (s->code, X86_ECX, tree->left->reg2, 4);
1824 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1825 x86_mov_reg_reg (s->code, X86_EDX, X86_ECX, 4);
1827 } else if (tree->left->reg2 != X86_EDX) {
1828 x86_mov_reg_reg (s->code, X86_EDX, tree->left->reg2, 4);
1831 if (!tree->last_instr) {
1833 x86_jump32 (s->code, s->epilog - 5);
1838 stmt: ARG_I8 (lreg) {
1839 x86_push_reg (s->code, tree->left->reg2);
1840 x86_push_reg (s->code, tree->left->reg1);
1843 stmt: BEQ (lreg, lreg) {
1844 guint8 *start = s->code;
1849 for (i = 0; i < 2; i ++) {
1851 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1852 o1 = 2 + s->code - s->start;
1853 x86_branch8 (s->code, X86_CC_NE, o2 - o1, FALSE);
1854 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1855 o2 = 6 + s->code - s->start;
1856 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - o2, TRUE);
1860 stmt: BNE_UN (lreg, lreg) {
1865 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1866 offset = 6 + s->code - s->start;
1867 x86_branch8 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
1868 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1869 offset = 6 + s->code - s->start;
1870 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
1873 stmt: BGE (lreg, lreg) {
1874 guint8 *start = s->code;
1875 gint32 o1, o2, oe, i;
1879 for (i = 0; i < 2; i ++) {
1881 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1882 o1 = 6 + s->code - s->start;
1883 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - o1, TRUE);
1884 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1885 o2 = 2 + s->code - s->start;
1886 x86_branch8 (s->code, X86_CC_NE, oe - o2, TRUE);
1887 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1888 oe = 6 + s->code - s->start;
1889 x86_branch32 (s->code, X86_CC_GE, tree->data.bb->addr - oe, FALSE);
1893 stmt: BGE_UN (lreg, lreg) {
1894 guint8 *start = s->code;
1895 gint32 o1, o2, oe, i;
1899 for (i = 0; i < 2; i ++) {
1901 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1902 o1 = 6 + s->code - s->start;
1903 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - o1, FALSE);
1904 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1905 o2 = 2 + s->code - s->start;
1906 x86_branch8 (s->code, X86_CC_NE, oe - o2, FALSE);
1907 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1908 oe = 6 + s->code - s->start;
1909 x86_branch32 (s->code, X86_CC_GE, tree->data.bb->addr - oe, FALSE);
1913 stmt: BGT (lreg, lreg) {
1914 guint8 *start = s->code;
1915 gint32 o1, o2, oe, i;
1919 for (i = 0; i < 2; i ++) {
1921 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1922 o1 = 6 + s->code - s->start;
1923 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - o1, TRUE);
1924 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1925 o2 = 2 + s->code - s->start;
1926 x86_branch8 (s->code, X86_CC_NE, oe - o2, TRUE);
1927 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1928 oe = 6 + s->code - s->start;
1929 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - oe, FALSE);
1933 stmt: BGT_UN (lreg, lreg) {
1934 guint8 *start = s->code;
1935 gint32 o1, o2, oe, i;
1939 for (i = 0; i < 2; i ++) {
1941 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1942 o1 = 6 + s->code - s->start;
1943 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - o1, FALSE);
1944 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1945 o2 = 2 + s->code - s->start;
1946 x86_branch8 (s->code, X86_CC_NE, oe - o2, FALSE);
1947 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1948 oe = 6 + s->code - s->start;
1949 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - oe, FALSE);
1953 stmt: BLT (lreg, lreg) {
1954 guint8 *start = s->code;
1955 gint32 o1, o2, oe, i;
1959 for (i = 0; i < 2; i ++) {
1961 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1962 o1 = 6 + s->code - s->start;
1963 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - o1, TRUE);
1964 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1965 o2 = 2 + s->code - s->start;
1966 x86_branch8 (s->code, X86_CC_NE, oe - o2, TRUE);
1967 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1968 oe = 6 + s->code - s->start;
1969 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - oe, FALSE);
1973 stmt: BLT_UN (lreg, lreg) {
1974 guint8 *start = s->code;
1975 gint32 o1, o2, oe, i;
1979 for (i = 0; i < 2; i ++) {
1981 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1982 o1 = 6 + s->code - s->start;
1983 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - o1, FALSE);
1984 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
1985 o2 = 2 + s->code - s->start;
1986 x86_branch8 (s->code, X86_CC_NE, oe - o2, FALSE);
1987 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1988 oe = 6 + s->code - s->start;
1989 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - oe, FALSE);
1993 stmt: BLE (lreg, lreg) {
1994 guint8 *start = s->code;
1995 gint32 o1, o2, oe, i;
1999 for (i = 0; i < 2; i ++) {
2001 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2002 o1 = 6 + s->code - s->start;
2003 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - o1, TRUE);
2004 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2005 o2 = 2 + s->code - s->start;
2006 x86_branch8 (s->code, X86_CC_NE, oe - o2, TRUE);
2007 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2008 oe = 6 + s->code - s->start;
2009 x86_branch32 (s->code, X86_CC_LE, tree->data.bb->addr - oe, FALSE);
2013 stmt: BLE_UN (lreg, lreg) {
2014 guint8 *start = s->code;
2015 gint32 o1, o2, oe, i;
2019 for (i = 0; i < 2; i ++) {
2021 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2022 o1 = 6 + s->code - s->start;
2023 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - o1, FALSE);
2024 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2025 o2 = 2 + s->code - s->start;
2026 x86_branch8 (s->code, X86_CC_NE, oe - o2, FALSE);
2027 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2028 oe = 6 + s->code - s->start;
2029 x86_branch32 (s->code, X86_CC_LE, tree->data.bb->addr - oe, FALSE);
2036 #stmt: STLOC (CONV_I4 (freg)) {
2038 # x86_fist_pop_membase (s->code, X86_EBP, tree->data.i, FALSE);
2041 reg: CONV_I4 (freg) {
2042 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
2043 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
2044 x86_pop_reg (s->code, tree->reg1);
2047 freg: CONV_R8 (freg) {
2051 freg: CONV_R8 (LDIND_I4 (ADDR_G)) {
2052 x86_fild (s->code, tree->left->left->data.p, FALSE);
2055 freg: CONV_R8 (reg) {
2056 /* I found no direct way to move an integer register to
2057 * the floating point stack, so we need to store the register
2060 x86_push_reg (s->code, tree->left->reg1);
2061 x86_fild_membase (s->code, X86_ESP, 0, FALSE);
2062 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
2065 freg: CONV_R4 (reg) {
2066 /* I found no direct way to move an integer register to
2067 * the floating point stack, so we need to store the register
2070 x86_push_reg (s->code, tree->left->reg1);
2071 x86_fild_membase (s->code, X86_ESP, 0, FALSE);
2072 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
2076 float f = *(float *)tree->data.p;
2083 x86_fld (s->code, tree->data.p, FALSE);
2087 double d = *(double *)tree->data.p;
2094 x86_fld (s->code, tree->data.p, TRUE);
2097 freg: LDIND_R4 (reg) {
2098 x86_fld_membase (s->code, tree->left->reg1, 0, FALSE);
2101 freg: LDIND_R8 (reg) {
2102 x86_fld_membase (s->code, tree->left->reg1, 0, TRUE);
2105 freg: LDIND_R8 (reg) {
2106 x86_fld_membase (s->code, tree->left->reg1, 0, TRUE);
2109 freg: ADD (freg, freg) {
2110 x86_fp_op_reg (s->code, X86_FADD, 1, TRUE);
2113 freg: SUB (freg, freg) {
2114 x86_fp_op_reg (s->code, X86_FSUB, 1, TRUE);
2117 freg: MUL (freg, freg) {
2118 x86_fp_op_reg (s->code, X86_FMUL, 1, TRUE);
2121 freg: DIV (freg, freg) {
2122 x86_fp_op_reg (s->code, X86_FDIV, 1, TRUE);
2125 #freg: REM (freg, freg) {
2126 # this does not work, since it does not pop a value from the stack,
2127 # and we need to test if the instruction is ready
2128 # x86_fprem1 (s->code);
2137 stmt: STIND_R4 (reg, freg) {
2138 x86_fst_membase (s->code, tree->left->reg1, 0, FALSE, TRUE);
2141 stmt: STIND_R8 (reg, freg) {
2142 x86_fst_membase (s->code, tree->left->reg1, 0, TRUE, TRUE);
2145 stmt: ARG_R4 (freg) {
2146 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
2147 x86_fst_membase (s->code, X86_ESP, 0, FALSE, TRUE);
2150 stmt: ARG_R8 (freg) {
2151 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
2152 x86_fst_membase (s->code, X86_ESP, 0, TRUE, TRUE);
2155 stmt: BEQ (freg, freg) {
2159 x86_fcompp (s->code);
2160 x86_fnstsw (s->code);
2161 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
2162 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
2163 offset = 6 + s->code - s->start;
2164 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, TRUE);
2167 stmt: BNE_UN (freg, freg) {
2171 x86_fcompp (s->code);
2172 x86_fnstsw (s->code);
2173 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
2174 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
2175 offset = 6 + s->code - s->start;
2176 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
2179 stmt: BLT (freg, freg) {
2183 x86_fcompp (s->code);
2184 x86_fnstsw (s->code);
2185 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
2186 offset = 6 + s->code - s->start;
2187 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, TRUE);
2190 stmt: BLT_UN (freg, freg) {
2194 x86_fcompp (s->code);
2195 x86_fnstsw (s->code);
2196 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
2197 offset = 6 + s->code - s->start;
2198 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, FALSE);
2201 stmt: BGE_UN (freg, freg) {
2205 x86_fcompp (s->code);
2206 x86_fnstsw (s->code);
2207 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
2208 offset = 6 + s->code - s->start;
2209 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
2212 stmt: BGT_UN (freg, freg) {
2216 x86_fcompp (s->code);
2217 x86_fnstsw (s->code);
2218 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
2219 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
2220 offset = 6 + s->code - s->start;
2221 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, FALSE);
2224 stmt: BLE_UN (freg, freg) {
2228 x86_fcompp (s->code);
2229 x86_fnstsw (s->code);
2230 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
2231 offset = 6 + s->code - s->start;
2232 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
2235 freg: CALL_R8 (this, LDIND_I4 (ADDR_G)) {
2236 MethodCallInfo *ci = tree->data.ci;
2237 int lreg = tree->left->reg1;
2243 if (ci->vtype_num) {
2244 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
2245 x86_lea_membase (s->code, treg, X86_EBP, offset);
2246 x86_push_reg (s->code, treg);
2249 if (tree->left->op != MB_TERM_NOP) {
2250 g_assert (lreg >= 0);
2251 x86_push_reg (s->code, lreg);
2254 x86_call_mem (s->code, tree->right->left->data.p);
2257 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
2260 freg: CALL_R8 (this, INTF_ADDR) {
2261 MethodCallInfo *ci = tree->data.ci;
2262 int lreg = tree->left->reg1;
2268 if (ci->vtype_num) {
2269 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
2270 x86_lea_membase (s->code, treg, X86_EBP, offset);
2271 x86_push_reg (s->code, treg);
2274 if (tree->left->op != MB_TERM_NOP) {
2275 g_assert (lreg >= 0);
2276 x86_push_reg (s->code, lreg);
2279 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2280 x86_mov_reg_membase (s->code, lreg, lreg,
2281 G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
2282 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
2283 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
2286 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
2289 freg: CALL_R8 (this, VFUNC_ADDR) {
2290 MethodCallInfo *ci = tree->data.ci;
2291 int lreg = tree->left->reg1;
2297 if (ci->vtype_num) {
2298 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
2299 x86_lea_membase (s->code, treg, X86_EBP, offset);
2300 x86_push_reg (s->code, treg);
2303 if (tree->left->op != MB_TERM_NOP) {
2304 g_assert (lreg >= 0);
2305 x86_push_reg (s->code, lreg);
2308 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2309 x86_call_virtual (s->code, lreg,
2310 G_STRUCT_OFFSET (MonoClass, vtable) + (tree->right->data.m->slot << 2));
2313 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
2318 if (!tree->last_instr) {
2320 x86_jump32 (s->code, s->epilog - 5);
2324 # support for value types
2328 vtype: LDIND_OBJ (reg) {
2330 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
2331 int size = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).size;
2333 if (tree->left->reg1 == X86_EAX)
2336 x86_push_reg (s->code, X86_EAX);
2337 x86_push_reg (s->code, X86_EDX);
2338 x86_push_reg (s->code, X86_ECX);
2340 x86_push_imm (s->code, size);
2341 x86_push_reg (s->code, tree->left->reg1);
2342 x86_lea_membase (s->code, treg, X86_EBP, offset);
2343 x86_push_reg (s->code, treg);
2344 x86_call_code (s->code, MEMCOPY);
2345 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
2347 x86_pop_reg (s->code, X86_ECX);
2348 x86_pop_reg (s->code, X86_EDX);
2349 x86_pop_reg (s->code, X86_EAX);
2352 stmt: STIND_OBJ (reg, vtype) {
2354 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->right->data.i).offset;
2355 int size = g_array_index (s->varinfo, MonoVarInfo, tree->right->data.i).size;
2357 if (tree->left->reg1 == X86_EAX)
2360 x86_push_reg (s->code, X86_EAX);
2361 x86_push_reg (s->code, X86_EDX);
2362 x86_push_reg (s->code, X86_ECX);
2364 x86_push_imm (s->code, size);
2365 x86_lea_membase (s->code, treg, X86_EBP, offset);
2366 x86_push_reg (s->code, treg);
2367 x86_push_reg (s->code, tree->left->reg1);
2368 x86_call_code (s->code, MEMCOPY);
2369 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
2371 x86_pop_reg (s->code, X86_ECX);
2372 x86_pop_reg (s->code, X86_EDX);
2373 x86_pop_reg (s->code, X86_EAX);
2376 stmt: ARG_OBJ (vtype) {
2378 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->left->data.i).offset;
2379 int size = g_array_index (s->varinfo, MonoVarInfo, tree->left->data.i).size;
2385 /* reserve space for the argument */
2386 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);
2388 x86_push_reg (s->code, X86_EAX);
2389 x86_push_reg (s->code, X86_EDX);
2390 x86_push_reg (s->code, X86_ECX);
2392 x86_push_imm (s->code, size);
2394 x86_lea_membase (s->code, treg, X86_EBP, offset);
2395 x86_push_reg (s->code, treg);
2397 x86_lea_membase (s->code, treg, X86_ESP, 5*4);
2398 x86_push_reg (s->code, treg);
2400 x86_call_code (s->code, MEMCOPY);
2401 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
2403 x86_pop_reg (s->code, X86_ECX);
2404 x86_pop_reg (s->code, X86_EDX);
2405 x86_pop_reg (s->code, X86_EAX);
2408 stmt: RETV (vtype) {
2410 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->left->data.i).offset;
2411 int size = g_array_index (s->varinfo, MonoVarInfo, tree->left->data.i).size;
2413 x86_push_imm (s->code, size);
2414 x86_lea_membase (s->code, treg, X86_EBP, offset);
2415 x86_push_reg (s->code, treg);
2416 x86_push_membase (s->code, X86_EBP, 8);
2418 x86_call_code (s->code, MEMCOPY);
2419 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
2421 if (!tree->last_instr) {
2423 x86_jump32 (s->code, s->epilog - 5);
2432 mono_llmult (gint64 a, gint64 b)
2438 mono_lldiv (gint64 a, gint64 b)
2444 mono_llrem (gint64 a, gint64 b)
2450 mono_lldiv_un (guint64 a, guint64 b)
2456 mono_llrem_un (guint64 a, guint64 b)
2462 mono_ctree_new (MonoMemPool *mp, int op, MBTree *left, MBTree *right)
2464 MBTree *t = mono_mempool_alloc0 (mp, sizeof (MBTree));
2472 t->svt = VAL_UNKNOWN;
2478 mono_ctree_new_leaf (MonoMemPool *mp, int op)
2480 return mono_ctree_new (mp, op, NULL, NULL);
2484 throw_exception (unsigned long eax, unsigned long ecx, unsigned long edx, unsigned long ebx,
2485 unsigned long esi, unsigned long edi, unsigned long ebp, unsigned long eip,
2488 MonoObject *exc = (gpointer)ecx;
2489 struct sigcontext ctx;
2501 arch_handle_exception (&ctx, exc);
2503 g_assert_not_reached ();
2507 get_throw_exception (void)
2509 static guint8 *start = NULL;
2515 code = start = g_malloc (1024);
2517 x86_push_reg (code, X86_ESP);
2518 x86_push_membase (code, X86_ESP, 4); /* IP */
2519 x86_push_reg (code, X86_EBP);
2520 x86_push_reg (code, X86_EDI);
2521 x86_push_reg (code, X86_ESI);
2522 x86_push_reg (code, X86_EBX);
2523 x86_push_reg (code, X86_EDX);
2524 x86_push_reg (code, X86_ECX);
2525 x86_push_reg (code, X86_EAX);
2526 x86_call_code (code, throw_exception);
2527 /* we should never reach this breakpoint */
2528 x86_breakpoint (code);
2535 MEMCOPY (void *dest, const void *src, size_t n)
2539 printf ("MEMCPY(%p to %p [%d]) ", src, dest, n);
2541 for (i = 0; i < l; i++)
2542 printf ("%02x ", *((guint8 *)src + i));
2545 return memcpy (dest, src, n);