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/metadata/appdomain.h>
22 #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]
50 unsigned last_instr:1;
79 gint64 mono_llmult (gint64 a, gint64 b);
80 guint64 mono_llmult_ovf_un (gpointer *exc, guint32 al, guint32 ah, guint32 bl, gint32 bh);
81 gint64 mono_lldiv (gint64 a, gint64 b);
82 gint64 mono_llrem (gint64 a, gint64 b);
83 guint64 mono_lldiv_un (guint64 a, guint64 b);
84 guint64 mono_llrem_un (guint64 a, guint64 b);
85 gpointer mono_ldsflda (MonoClass *klass, int offset);
87 gpointer arch_get_lmf_addr (void);
90 mono_array_new_wrapper (MonoClass *eclass, guint32 n);
92 mono_object_new_wrapper (MonoClass *klass);
94 mono_string_new_wrapper (const char *text);
96 mono_ldstr_wrapper (MonoImage *image, guint32 index);
99 get_mono_object_isinst (void);
101 #define MB_OPT_LEVEL 1
103 #if MB_OPT_LEVEL == 0
104 #define MB_USE_OPT1(c) 65535
105 #define MB_USE_OPT2(c) 65535
107 #if MB_OPT_LEVEL == 1
108 #define MB_USE_OPT1(c) c
109 #define MB_USE_OPT2(c) 65535
111 #if MB_OPT_LEVEL >= 2
112 #define MB_USE_OPT1(c) c
113 #define MB_USE_OPT2(c) c
118 #define REAL_PRINT_REG(text,reg) \
119 g_assert (reg >= 0); \
120 x86_push_reg (s->code, X86_EAX); \
121 x86_push_reg (s->code, X86_EDX); \
122 x86_push_reg (s->code, X86_ECX); \
123 x86_push_reg (s->code, reg); \
124 x86_push_imm (s->code, reg); \
125 x86_push_imm (s->code, text " %d %p\n"); \
126 x86_mov_reg_imm (s->code, X86_EAX, printf); \
127 x86_call_reg (s->code, X86_EAX); \
128 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 3*4); \
129 x86_pop_reg (s->code, X86_ECX); \
130 x86_pop_reg (s->code, X86_EDX); \
131 x86_pop_reg (s->code, X86_EAX);
134 #define MEMCOPY debug_memcpy
135 void *MEMCOPY (void *dest, const void *src, size_t n);
137 #define PRINT_REG(text,reg) REAL_PRINT_REG(text,reg)
140 #define MEMCOPY memcpy
142 #define PRINT_REG(x,y)
146 /* The call instruction for virtual functions must have a known
147 * size (used by x86_magic_trampoline)
149 #define x86_call_virtual(inst,basereg,disp) \
151 *(inst)++ = (unsigned char)0xff; \
152 x86_address_byte ((inst), 2, 2, (basereg)); \
153 x86_imm_emit32 ((inst), (disp)); \
156 /* emit an exception if condition is fail */
157 #define EMIT_COND_SYSTEM_EXCEPTION(cond,signed,exc_name) \
159 x86_branch8 (s->code, cond, 12, signed); \
160 x86_push_imm (s->code, exc_name); \
161 x86_mov_reg_imm (s->code, X86_EAX, \
162 arch_get_throw_exception_by_name ()); \
163 x86_call_reg (s->code, X86_EAX); \
169 # terminal definitions
173 %term CONST_I4 CONST_I8 CONST_R4 CONST_R8
174 %term LDIND_I1 LDIND_U1 LDIND_I2 LDIND_U2 LDIND_I4 LDIND_REF LDIND_I8 LDIND_R4 LDIND_R8
175 %term LDIND_U4 LDIND_OBJ
176 %term STIND_I1 STIND_I2 STIND_I4 STIND_REF STIND_I8 STIND_R4 STIND_R8 STIND_OBJ
177 %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
178 %term BREAK SWITCH BR RET_VOID RET RET_OBJ ENDFINALLY
179 %term ADD ADD_OVF ADD_OVF_UN SUB SUB_OVF SUB_OVF_UN MUL MUL_OVF MUL_OVF_UN
180 %term DIV DIV_UN REM REM_UN AND OR XOR SHL SHR SHR_UN NEG NOT
181 %term BLT BLT_UN BEQ BNE_UN BRTRUE BRFALSE BGE BGE_UN BLE BLE_UN BGT BGT_UN
182 %term CEQ CLT CLT_UN CGT CGT_UN
183 %term CONV_I4 CONV_I1 CONV_I2 CONV_I8 CONV_U8 CONV_R4 CONV_R8
184 %term INTF_ADDR VFUNC_ADDR NOP NEWARR NEWOBJ NEWSTRUCT CPOBJ POP INITOBJ
185 %term ISINST CASTCLASS UNBOX
186 %term CONV_OVF_I1 CONV_OVF_U1 CONV_OVF_I2 CONV_OVF_U2 CONV_OVF_U4 CONV_OVF_U8 CONV_OVF_I4
187 %term CONV_OVF_I4_UN CONV_OVF_U1_UN CONV_OVF_U2_UN
188 %term CONV_OVF_I2_UN CONV_OVF_I8_UN CONV_OVF_I1_UN
189 %term EXCEPTION THROW RETHROW HANDLER SAVE_LMF RESTORE_LMF
190 %term LDLEN LDELEMA LDFTN TOSTRING LDSTR LDSFLDA
206 tree->data.ainfo.offset = tree->data.i;
207 tree->data.ainfo.amode = AMImmediate;
211 tree->data.ainfo.offset = tree->data.i;
212 tree->data.ainfo.amode = AMImmediate;
215 acon: ADD (ADDR_G, CONST_I4) {
216 tree->data.ainfo.offset = (unsigned)tree->left->data.p + tree->right->data.i;
217 tree->data.ainfo.amode = AMImmediate;
223 tree->data.ainfo.offset = 0;
224 tree->data.ainfo.basereg = tree->reg1;
225 tree->data.ainfo.amode = AMBase;
228 base: ADD (reg, acon) {
229 tree->data.ainfo.offset = tree->right->data.i;
230 tree->data.ainfo.basereg = tree->left->reg1;
231 tree->data.ainfo.amode = AMBase;
235 tree->data.ainfo.offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
236 tree->data.ainfo.basereg = X86_EBP;
237 tree->data.ainfo.amode = AMBase;
241 tree->data.ainfo.offset = 0;
242 tree->data.ainfo.indexreg = tree->reg1;
243 tree->data.ainfo.shift = 0;
244 tree->data.ainfo.amode = AMIndex;
247 index: SHL (reg, CONST_I4) {
248 tree->data.ainfo.offset = 0;
249 tree->data.ainfo.amode = AMIndex;
250 tree->data.ainfo.indexreg = tree->left->reg1;
251 tree->data.ainfo.shift = tree->right->data.i;
253 MBCOND (tree->right->data.i == 0 ||
254 tree->right->data.i == 1 ||
255 tree->right->data.i == 2 ||
256 tree->right->data.i == 3);
261 index: MUL (reg, CONST_I4) {
262 static int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
264 tree->data.ainfo.offset = 0;
265 tree->data.ainfo.amode = AMIndex;
266 tree->data.ainfo.indexreg = tree->left->reg1;
267 tree->data.ainfo.shift = fast_log2 [tree->right->data.i];
269 MBCOND (tree->right->data.i == 1 ||
270 tree->right->data.i == 2 ||
271 tree->right->data.i == 4 ||
272 tree->right->data.i == 8);
281 addr: ADD (index, base) {
282 tree->data.ainfo.offset = tree->right->data.ainfo.offset;
283 tree->data.ainfo.basereg = tree->right->data.ainfo.basereg;
284 tree->data.ainfo.amode = tree->left->data.ainfo.amode |
285 tree->right->data.ainfo.amode;
286 tree->data.ainfo.shift = tree->left->data.ainfo.shift;
287 tree->data.ainfo.indexreg = tree->left->data.ainfo.indexreg;
290 # we pass exception in ECX to catch handler
292 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
294 if (tree->reg1 != X86_ECX)
295 x86_mov_reg_reg (s->code, tree->reg1, X86_ECX, 4);
297 /* store it so that we can RETHROW it later */
298 x86_mov_membase_reg (s->code, X86_EBP, offset, tree->reg1, 4);
302 tree->is_jump = TRUE;
304 x86_push_reg (s->code, tree->left->reg1);
305 x86_call_code (s->code, arch_get_throw_exception ());
309 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
311 tree->is_jump = TRUE;
313 x86_push_membase (s->code, X86_EBP, offset);
314 x86_call_code (s->code, arch_get_throw_exception ());
318 gint32 addr = tree->data.bb->addr - tree->addr - 5;
319 tree->is_jump = TRUE;
320 x86_call_imm (s->code, addr);
328 tree->is_jump = TRUE;
331 /* save all caller saved regs */
332 x86_push_reg (s->code, X86_EBX);
333 x86_push_reg (s->code, X86_EDI);
334 x86_push_reg (s->code, X86_ESI);
335 x86_push_reg (s->code, X86_EBP);
338 x86_push_imm (s->code, s->code);
340 /* save method info */
341 x86_push_imm (s->code, tree->data.m);
342 /* get the address of lmf for the current thread */
343 x86_call_code (s->code, arch_get_lmf_addr);
345 x86_push_reg (s->code, X86_EAX);
346 /* push *lfm (previous_lmf) */
347 x86_push_membase (s->code, X86_EAX, 0);
349 x86_mov_membase_reg (s->code, X86_EAX, 0, X86_ESP, 4);
353 /* ebx = previous_lmf */
354 x86_pop_reg (s->code, X86_EBX);
356 x86_pop_reg (s->code, X86_EDI);
357 /* *(lmf) = previous_lmf */
358 x86_mov_membase_reg (s->code, X86_EDI, 0, X86_EBX, 4);
360 /* discard method info */
361 x86_pop_reg (s->code, X86_ESI);
363 /* discard save IP */
364 x86_pop_reg (s->code, X86_ESI);
366 /* restore caller saved regs */
367 x86_pop_reg (s->code, X86_EBP);
368 x86_pop_reg (s->code, X86_ESI);
369 x86_pop_reg (s->code, X86_EDI);
370 x86_pop_reg (s->code, X86_EBX);
373 stmt: STIND_I4 (addr, reg) {
374 PRINT_REG ("STIND_I4", tree->right->reg1);
376 switch (tree->left->data.ainfo.amode) {
379 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
383 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
384 tree->left->data.ainfo.offset, tree->right->reg1, 4);
387 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
388 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
389 tree->right->reg1, 4);
392 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
393 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
394 tree->right->reg1, 4);
399 stmt: STIND_REF (addr, reg) {
400 PRINT_REG ("STIND_REF", tree->right->reg1);
402 switch (tree->left->data.ainfo.amode) {
405 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
409 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
410 tree->left->data.ainfo.offset, tree->right->reg1, 4);
413 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
414 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
415 tree->right->reg1, 4);
418 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
419 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
420 tree->right->reg1, 4);
425 stmt: STIND_I1 (addr, reg) {
426 PRINT_REG ("STIND_I1", tree->right->reg1);
428 switch (tree->left->data.ainfo.amode) {
431 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 1);
435 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
436 tree->left->data.ainfo.offset, tree->right->reg1, 1);
439 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
440 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
441 tree->right->reg1, 1);
444 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
445 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
446 tree->right->reg1, 1);
451 stmt: STIND_I2 (addr, reg) {
452 PRINT_REG ("STIND_I2", tree->right->reg1);
454 switch (tree->left->data.ainfo.amode) {
457 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 2);
461 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
462 tree->left->data.ainfo.offset, tree->right->reg1, 2);
465 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
466 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
467 tree->right->reg1, 2);
470 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
471 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
472 tree->right->reg1, 2);
477 reg: LDIND_I4 (addr) {
479 switch (tree->left->data.ainfo.amode) {
482 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
486 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
487 tree->left->data.ainfo.offset, 4);
490 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
491 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
494 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
495 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
496 tree->left->data.ainfo.shift, 4);
501 PRINT_REG ("LDIND_I4", tree->reg1);
504 reg: LDIND_REF (addr) {
506 switch (tree->left->data.ainfo.amode) {
509 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
513 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
514 tree->left->data.ainfo.offset, 4);
517 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
518 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
521 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
522 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
523 tree->left->data.ainfo.shift, 4);
528 PRINT_REG ("LDIND_REF", tree->reg1);
531 reg: LDIND_I1 (addr) {
532 switch (tree->left->data.ainfo.amode) {
535 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, FALSE);
539 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
540 tree->left->data.ainfo.offset, TRUE, FALSE);
543 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
544 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, TRUE, FALSE);
547 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
548 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
549 tree->left->data.ainfo.shift, TRUE, FALSE);
553 PRINT_REG ("LDIND_I1", tree->reg1);
556 reg: LDIND_U1 (addr) {
557 switch (tree->left->data.ainfo.amode) {
560 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, FALSE);
564 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
565 tree->left->data.ainfo.offset, FALSE, FALSE);
568 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
569 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, FALSE, FALSE);
572 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
573 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
574 tree->left->data.ainfo.shift, FALSE, FALSE);
578 PRINT_REG ("LDIND_U1", tree->reg1);
581 reg: LDIND_I2 (addr) {
582 switch (tree->left->data.ainfo.amode) {
585 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, TRUE);
589 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
590 tree->left->data.ainfo.offset, TRUE, TRUE);
593 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
594 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, TRUE, TRUE);
597 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
598 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
599 tree->left->data.ainfo.shift, TRUE, TRUE);
603 PRINT_REG ("LDIND_U2", tree->reg1);
606 reg: LDIND_U2 (addr) {
607 switch (tree->left->data.ainfo.amode) {
610 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, TRUE);
614 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
615 tree->left->data.ainfo.offset, FALSE, TRUE);
618 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
619 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, FALSE, TRUE);
622 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
623 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
624 tree->left->data.ainfo.shift, FALSE, TRUE);
628 PRINT_REG ("LDIND_U2", tree->reg1);
631 reg: LDIND_U4 (addr) {
632 switch (tree->left->data.ainfo.amode) {
635 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
639 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
640 tree->left->data.ainfo.offset, 4);
643 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
644 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
647 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
648 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
649 tree->left->data.ainfo.shift, 4);
653 PRINT_REG ("LDIND_U4", tree->reg1);
657 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
658 x86_lea_membase (s->code, tree->reg1, X86_EBP, offset);
660 PRINT_REG ("ADDR_L", tree->reg1);
665 x86_mov_reg_imm (s->code, tree->reg1, tree->data.p);
669 x86_alu_reg_imm (s->code, X86_AND, tree->left->reg1, 0xff);
671 if (tree->reg1 != tree->left->reg1)
672 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
676 x86_alu_reg_imm (s->code, X86_AND, tree->left->reg1, 0xffff);
678 if (tree->reg1 != tree->left->reg1)
679 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
683 x86_mov_reg_imm (s->code, tree->reg1, tree->data.i);
687 if (tree->reg1 != tree->left->reg1)
688 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
689 PRINT_REG ("CONV_I4", tree->left->reg1);
692 reg: CONV_OVF_U4 (reg) {
693 /* Keep in sync with CONV_OVF_I4_UN below, they are the same on 32-bit machines */
694 x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
695 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
696 if (tree->reg1 != tree->left->reg1)
697 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
700 reg: CONV_OVF_I4_UN (reg) {
701 /* Keep in sync with CONV_OVF_U4 above, they are the same on 32-bit machines */
702 x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
703 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
704 if (tree->reg1 != tree->left->reg1)
705 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
708 reg: CONV_OVF_I1 (reg) {
709 /* probe value to be within -128 to 127 */
710 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 127);
711 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, TRUE, "OverflowException");
712 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, -128);
713 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GT, TRUE, "OverflowException");
714 if (tree->reg1 != tree->left->reg1)
715 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
718 reg: CONV_OVF_I1_UN (reg) {
719 /* probe values between 0 to 128 */
720 x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff80);
721 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
722 if (tree->reg1 != tree->left->reg1)
723 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
726 reg: CONV_OVF_U1 (reg) {
727 /* Keep in sync with CONV_OVF_U1_UN routine below, they are the same on 32-bit machines */
728 /* probe value to be within 0 to 255 */
729 x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff00);
730 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
731 if (tree->reg1 != tree->left->reg1)
732 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
735 reg: CONV_OVF_U1_UN (reg) {
736 /* Keep in sync with CONV_OVF_U1 routine above, they are the same on 32-bit machines */
737 /* probe value to be within 0 to 255 */
738 x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff00);
739 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
740 if (tree->reg1 != tree->left->reg1)
741 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
744 reg: CONV_OVF_I2 (reg) {
745 /* Probe value to be within -32768 and 32767 */
746 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 32767);
747 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, TRUE, "OverflowException");
748 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, -32768);
749 // fixme: check branch
750 g_assert_not_reached ();
751 x86_branch8 (s->code, X86_CC_LT, -17, TRUE);
752 if (tree->reg1 != tree->left->reg1)
753 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
756 reg: CONV_OVF_U2 (reg) {
757 /* Keep in sync with CONV_OVF_U2_UN below, they are the same on 32-bit machines */
758 /* Probe value to be within 0 and 65535 */
759 x86_test_reg_imm (s->code, tree->left->reg1, 0xffff0000);
760 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
761 if (tree->reg1 != tree->left->reg1)
762 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
765 reg: CONV_OVF_U2_UN (reg) {
766 /* Keep in sync with CONV_OVF_U2 above, they are the same on 32-bit machines */
767 /* Probe value to be within 0 and 65535 */
768 x86_test_reg_imm (s->code, tree->left->reg1, 0xffff0000);
769 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
770 if (tree->reg1 != tree->left->reg1)
771 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
774 reg: CONV_OVF_I2_UN (reg) {
775 /* Convert uint value into short, value within 0 and 32767 */
776 x86_test_reg_imm (s->code, tree->left->reg1, 0xffff8000);
777 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
778 if (tree->reg1 != tree->left->reg1)
779 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
782 reg: MUL (reg, reg) {
783 x86_imul_reg_reg (s->code, tree->left->reg1, tree->right->reg1);
785 if (tree->reg1 != tree->left->reg1)
786 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
789 reg: MUL_OVF (reg, reg) {
790 x86_imul_reg_reg (s->code, tree->left->reg1, tree->right->reg1);
791 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
793 if (tree->reg1 != tree->left->reg1)
794 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
797 reg: MUL_OVF_UN (reg, reg) {
798 //fixme: implement me
799 g_assert_not_reached ();
802 reg: DIV (reg, reg) {
803 g_assert (tree->right->reg1 != X86_EAX);
805 if (tree->left->reg1 != X86_EAX)
806 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
809 x86_div_reg (s->code, tree->right->reg1, TRUE);
811 g_assert (tree->reg1 == X86_EAX &&
812 tree->reg2 == X86_EDX);
815 reg: DIV_UN (reg, reg) {
816 g_assert (tree->right->reg1 != X86_EAX);
818 if (tree->left->reg1 != X86_EAX)
819 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
822 x86_div_reg (s->code, tree->right->reg1, FALSE);
824 g_assert (tree->reg1 == X86_EAX &&
825 tree->reg2 == X86_EDX);
828 reg: REM (reg, reg) {
829 g_assert (tree->right->reg1 != X86_EAX);
831 if (tree->left->reg1 != X86_EAX)
832 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
835 x86_div_reg (s->code, tree->right->reg1, TRUE);
836 x86_mov_reg_reg (s->code, X86_EAX, X86_EDX, 4);
838 g_assert (tree->reg1 == X86_EAX &&
839 tree->reg2 == X86_EDX);
842 reg: REM_UN (reg, reg) {
843 g_assert (tree->right->reg1 != X86_EAX);
845 if (tree->left->reg1 != X86_EAX)
846 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
849 x86_div_reg (s->code, tree->right->reg1, FALSE);
850 x86_mov_reg_reg (s->code, X86_EAX, X86_EDX, 4);
852 g_assert (tree->reg1 == X86_EAX &&
853 tree->reg2 == X86_EDX);
856 reg: ADD (reg, CONST_I4) "MB_USE_OPT1(0)" {
857 if (tree->right->data.i == 1)
858 x86_inc_reg (s->code, tree->left->reg1);
860 x86_alu_reg_imm (s->code, X86_ADD, tree->left->reg1, tree->right->data.i);
862 if (tree->reg1 != tree->left->reg1)
863 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
867 reg: ADD (reg, reg) {
868 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
870 if (tree->reg1 != tree->left->reg1)
871 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
874 reg: ADD_OVF (reg, reg) {
875 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
876 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
878 if (tree->reg1 != tree->left->reg1)
879 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
882 reg: ADD_OVF_UN (reg, reg) {
883 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
884 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
886 if (tree->reg1 != tree->left->reg1)
887 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
890 reg: SUB (reg, CONST_I4) "MB_USE_OPT1(0)" {
891 if (tree->right->data.i == 1)
892 x86_dec_reg (s->code, tree->left->reg1);
894 x86_alu_reg_imm (s->code, X86_SUB, tree->left->reg1, tree->right->data.i);
896 if (tree->reg1 != tree->left->reg1)
897 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
900 reg: SUB (reg, reg) {
901 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
903 if (tree->reg1 != tree->left->reg1)
904 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
907 reg: SUB_OVF (reg, reg) {
908 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
909 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
911 if (tree->reg1 != tree->left->reg1)
912 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
915 reg: SUB_OVF_UN (reg, reg) {
916 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
917 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
919 if (tree->reg1 != tree->left->reg1)
920 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
923 reg: CEQ (reg, reg) {
924 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
925 x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
926 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
929 reg: CGT (reg, reg) {
930 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
931 x86_set_reg (s->code, X86_CC_GT, tree->reg1, TRUE);
932 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
935 reg: CGT_UN (reg, reg) {
936 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
937 x86_set_reg (s->code, X86_CC_GT, tree->reg1, FALSE);
938 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
941 reg: CLT (reg, reg) {
942 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
943 x86_set_reg (s->code, X86_CC_LT, tree->reg1, TRUE);
944 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
947 reg: CLT_UN (reg, reg) {
948 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
949 x86_set_reg (s->code, X86_CC_LT, tree->reg1, FALSE);
950 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
953 reg: AND (reg, reg) {
954 x86_alu_reg_reg (s->code, X86_AND, tree->left->reg1, tree->right->reg1);
956 if (tree->reg1 != tree->left->reg1)
957 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
961 x86_alu_reg_reg (s->code, X86_OR, tree->left->reg1, tree->right->reg1);
963 if (tree->reg1 != tree->left->reg1)
964 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
967 reg: XOR (reg, reg) {
968 x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->right->reg1);
970 if (tree->reg1 != tree->left->reg1)
971 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
975 x86_neg_reg (s->code, tree->left->reg1);
977 if (tree->reg1 != tree->left->reg1)
978 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
982 x86_not_reg (s->code, tree->left->reg1);
984 if (tree->reg1 != tree->left->reg1)
985 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
988 reg: SHL (reg, CONST_I4) {
989 x86_shift_reg_imm (s->code, X86_SHL, tree->left->reg1, tree->right->data.i);
991 if (tree->reg1 != tree->left->reg1)
992 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
995 reg: SHL (reg, reg) {
996 if (tree->right->reg1 != X86_ECX)
997 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
998 x86_shift_reg (s->code, X86_SHL, tree->left->reg1);
1000 if (tree->reg1 != tree->left->reg1)
1001 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1003 g_assert (tree->reg1 != X86_ECX &&
1004 tree->left->reg1 != X86_ECX);
1007 reg: SHR (reg, CONST_I4) {
1008 x86_shift_reg_imm (s->code, X86_SAR, tree->left->reg1, tree->right->data.i);
1010 if (tree->reg1 != tree->left->reg1)
1011 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1014 reg: SHR (reg, reg) {
1015 if (tree->right->reg1 != X86_ECX)
1016 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1017 x86_shift_reg (s->code, X86_SAR, tree->left->reg1);
1019 if (tree->reg1 != tree->left->reg1)
1020 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1022 g_assert (tree->reg1 != X86_ECX &&
1023 tree->left->reg1 != X86_ECX);
1026 reg: SHR_UN (reg, CONST_I4) {
1027 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg1, tree->right->data.i);
1029 if (tree->reg1 != tree->left->reg1)
1030 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1033 reg: SHR_UN (reg, reg) {
1034 if (tree->right->reg1 != X86_ECX)
1035 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1036 x86_shift_reg (s->code, X86_SHR, tree->left->reg1);
1038 if (tree->reg1 != tree->left->reg1)
1039 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1041 g_assert (tree->reg1 != X86_ECX &&
1042 tree->left->reg1 != X86_ECX);
1045 reg: LDSFLDA (CONST_I4) {
1046 if (tree->reg1 != X86_EAX)
1047 x86_push_reg (s->code, X86_EAX);
1048 x86_push_reg (s->code, X86_ECX);
1049 x86_push_reg (s->code, X86_EDX);
1051 x86_push_imm (s->code, tree->left->data.i);
1052 x86_push_imm (s->code, tree->data.klass);
1053 x86_mov_reg_imm (s->code, X86_EAX, mono_ldsflda);
1054 x86_call_reg (s->code, X86_EAX);
1055 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1057 x86_pop_reg (s->code, X86_EDX);
1058 x86_pop_reg (s->code, X86_ECX);
1059 if (tree->reg1 != X86_EAX) {
1060 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1061 x86_pop_reg (s->code, X86_EAX);
1067 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
1068 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NE, TRUE, "NullReferenceException");
1070 x86_mov_reg_membase (s->code, tree->reg1, tree->left->reg1,
1071 G_STRUCT_OFFSET (MonoArray, bounds), 4);
1072 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1,
1073 G_STRUCT_OFFSET (MonoArrayBounds, length), 4);
1076 reg: LDELEMA (reg, reg) {
1077 x86_alu_reg_membase (s->code, X86_CMP, tree->right->reg1, tree->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length));
1078 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LT, FALSE, "IndexOutOfRangeException");
1080 if (tree->data.i == 1 || tree->data.i == 2 ||
1081 tree->data.i == 4 || tree->data.i == 8) {
1082 static int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
1083 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1,
1084 G_STRUCT_OFFSET (MonoArray, vector), tree->right->reg1,
1085 fast_log2 [tree->data.i]);
1087 x86_imul_reg_reg_imm (s->code, tree->right->reg1, tree->right->reg1, tree->data.i);
1088 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
1089 x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, G_STRUCT_OFFSET (MonoArray, vector));
1094 if (tree->reg1 != X86_EAX)
1095 x86_push_reg (s->code, X86_EAX);
1096 x86_push_reg (s->code, X86_ECX);
1097 x86_push_reg (s->code, X86_EDX);
1099 x86_push_imm (s->code, tree->data.p);
1100 x86_push_imm (s->code, s->method->klass->image);
1101 x86_mov_reg_imm (s->code, X86_EAX, mono_ldstr_wrapper);
1102 x86_call_reg (s->code, X86_EAX);
1103 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1105 x86_pop_reg (s->code, X86_EDX);
1106 x86_pop_reg (s->code, X86_ECX);
1107 if (tree->reg1 != X86_EAX) {
1108 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1109 x86_pop_reg (s->code, X86_EAX);
1112 PRINT_REG ("LDSTR", tree->reg1);
1115 reg: TOSTRING (reg) {
1116 guint8 *start = s->code, *l1, *le;
1119 tree->is_jump = TRUE;
1122 for (i = 0; i < 2; i++) {
1125 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
1126 x86_branch8 (s->code, X86_CC_EQ, le - l1, FALSE);
1129 if (tree->reg1 != X86_EAX)
1130 x86_push_reg (s->code, X86_EAX);
1131 x86_push_reg (s->code, X86_ECX);
1132 x86_push_reg (s->code, X86_EDX);
1134 x86_push_reg (s->code, tree->left->reg1);
1135 x86_mov_reg_imm (s->code, X86_EAX, mono_string_new_wrapper);
1136 x86_call_reg (s->code, X86_EAX);
1137 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
1139 x86_pop_reg (s->code, X86_EDX);
1140 x86_pop_reg (s->code, X86_ECX);
1141 if (tree->reg1 != X86_EAX) {
1142 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1143 x86_pop_reg (s->code, X86_EAX);
1151 if (tree->reg1 != X86_EAX)
1152 x86_push_reg (s->code, X86_EAX);
1153 x86_push_reg (s->code, X86_ECX);
1154 x86_push_reg (s->code, X86_EDX);
1156 x86_push_reg (s->code, tree->left->reg1);
1157 x86_push_imm (s->code, tree->data.p);
1158 x86_mov_reg_imm (s->code, X86_EAX, mono_array_new_wrapper);
1159 x86_call_reg (s->code, X86_EAX);
1160 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer) + 4);
1162 x86_pop_reg (s->code, X86_EDX);
1163 x86_pop_reg (s->code, X86_ECX);
1164 if (tree->reg1 != X86_EAX) {
1165 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1166 x86_pop_reg (s->code, X86_EAX);
1169 PRINT_REG ("NEWARR", tree->reg1);
1173 if (tree->reg1 != X86_EAX)
1174 x86_push_reg (s->code, X86_EAX);
1175 x86_push_reg (s->code, X86_ECX);
1176 x86_push_reg (s->code, X86_EDX);
1178 x86_push_imm (s->code, tree->data.klass);
1179 x86_mov_reg_imm (s->code, X86_EAX, mono_object_new_wrapper);
1180 x86_call_reg (s->code, X86_EAX);
1181 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
1183 x86_pop_reg (s->code, X86_EDX);
1184 x86_pop_reg (s->code, X86_ECX);
1185 if (tree->reg1 != X86_EAX) {
1186 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1187 x86_pop_reg (s->code, X86_EAX);
1189 PRINT_REG ("NEWOBJ", tree->reg1);
1193 int size = tree->data.i;
1196 g_assert (size > 0);
1201 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);
1202 x86_mov_reg_reg (s->code, tree->reg1, X86_ESP, 4);
1206 if (tree->reg1 != tree->left->reg1)
1207 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1209 x86_alu_reg_imm (s->code, X86_CMP, tree->reg1, 0);
1210 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NE, TRUE, "NullReferenceException");
1212 x86_push_reg (s->code, tree->reg1);
1213 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, 0, 4);
1214 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, 0, 4);
1215 x86_alu_membase_imm (s->code, X86_CMP, tree->reg1,
1216 G_STRUCT_OFFSET (MonoClass, element_class), ((int)(tree->data.klass->element_class)));
1217 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "InvalidCastException");
1218 x86_pop_reg (s->code, tree->reg1);
1219 x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, sizeof (MonoObject));
1222 reg: CASTCLASS (reg) {
1223 guint8 *start = s->code, *l1, *l2, *le;
1226 tree->is_jump = TRUE;
1227 l1 = l2 = le = NULL;
1229 for (i = 0; i < 2; i++) {
1232 if (tree->reg1 != X86_EAX)
1233 x86_push_reg (s->code, X86_EAX);
1235 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
1236 x86_branch8 (s->code, X86_CC_EQ, le - l2, FALSE);
1238 x86_push_reg (s->code, X86_ECX);
1239 x86_push_reg (s->code, X86_EDX);
1241 x86_push_imm (s->code, tree->data.klass);
1242 x86_push_reg (s->code, tree->left->reg1);
1243 x86_mov_reg_imm (s->code, X86_EAX, mono_object_isinst);
1244 x86_call_reg (s->code, X86_EAX);
1245 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1247 x86_pop_reg (s->code, X86_EDX);
1248 x86_pop_reg (s->code, X86_ECX);
1250 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0);
1251 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NE, TRUE, "InvalidCastException");
1252 if (tree->reg1 != X86_EAX) {
1253 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1254 x86_pop_reg (s->code, X86_EAX);
1263 if (tree->reg1 != X86_EAX)
1264 x86_push_reg (s->code, X86_EAX);
1265 x86_push_reg (s->code, X86_ECX);
1266 x86_push_reg (s->code, X86_EDX);
1268 x86_push_imm (s->code, tree->data.klass);
1269 x86_push_reg (s->code, tree->left->reg1);
1270 x86_mov_reg_imm (s->code, X86_EAX, mono_object_isinst);
1271 x86_call_reg (s->code, X86_EAX);
1272 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1274 x86_pop_reg (s->code, X86_EDX);
1275 x86_pop_reg (s->code, X86_ECX);
1276 if (tree->reg1 != X86_EAX) {
1277 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1278 x86_pop_reg (s->code, X86_EAX);
1283 stmt: INITOBJ (reg) {
1288 if (i == 1 || i == 2 || i == 4) {
1291 if (tree->left->reg1 != X86_EAX)
1294 x86_push_reg (s->code, t);
1295 x86_alu_reg_reg (s->code, X86_XOR, t, t);
1297 switch (tree->data.i) {
1299 x86_mov_regp_reg (s->code, tree->left->reg1, t, 4);
1302 x86_mov_regp_reg (s->code, tree->left->reg1, t, 4);
1305 x86_mov_regp_reg (s->code, tree->left->reg1, t, 4);
1308 x86_pop_reg (s->code, t);
1313 i = tree->data.i / 4;
1314 j = tree->data.i % 4;
1316 x86_push_reg (s->code, X86_EAX);
1318 if (tree->left->reg1 != X86_EDI) {
1319 x86_push_reg (s->code, X86_EDI);
1320 x86_mov_reg_reg (s->code, X86_EDI, tree->left->reg1, 4);
1324 x86_push_reg (s->code, X86_ECX);
1325 x86_alu_reg_reg (s->code, X86_XOR, X86_EAX, X86_EAX);
1326 x86_mov_reg_imm (s->code, X86_ECX, i);
1328 x86_prefix (s->code, X86_REP_PREFIX);
1329 x86_stosl (s->code);
1330 x86_pop_reg (s->code, X86_ECX);
1334 for (i = 0; i < j; i++)
1335 x86_stosb (s->code);
1337 if (tree->left->reg1 != X86_EDI)
1338 x86_pop_reg (s->code, X86_EDI);
1340 x86_pop_reg (s->code, X86_EAX);
1348 gint32 addr = tree->data.bb->addr - tree->addr - 5;
1349 tree->is_jump = TRUE;
1351 x86_jump32 (s->code, addr);
1354 stmt: BLT (reg, reg) 1 {
1357 tree->is_jump = TRUE;
1358 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1359 offset = 6 + s->code - s->start;
1360 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - offset, TRUE);
1363 stmt: BLT (reg, CONST_I4) "MB_USE_OPT1(0)" {
1366 tree->is_jump = TRUE;
1367 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1368 offset = 6 + s->code - s->start;
1369 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - offset, TRUE);
1372 stmt: BLT_UN (reg, reg) 1 {
1375 tree->is_jump = TRUE;
1376 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1377 offset = 6 + s->code - s->start;
1378 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - offset, FALSE);
1381 stmt: BLT_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1384 tree->is_jump = TRUE;
1385 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1386 offset = 6 + s->code - s->start;
1387 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - offset, FALSE);
1390 stmt: BGT (reg, reg) 1 {
1393 tree->is_jump = TRUE;
1394 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1395 offset = 6 + s->code - s->start;
1396 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - offset, TRUE);
1399 stmt: BGT (reg, CONST_I4) "MB_USE_OPT1(0)" {
1402 tree->is_jump = TRUE;
1403 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1404 offset = 6 + s->code - s->start;
1405 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - offset, TRUE);
1408 stmt: BGT_UN (reg, reg) 1 {
1411 tree->is_jump = TRUE;
1412 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1413 offset = 6 + s->code - s->start;
1414 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - offset, FALSE);
1417 stmt: BGT_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1420 tree->is_jump = TRUE;
1421 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1422 offset = 6 + s->code - s->start;
1423 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - offset, FALSE);
1426 stmt: BEQ (reg, CONST_I4) "MB_USE_OPT1(0)" {
1429 tree->is_jump = TRUE;
1430 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1431 offset = 6 + s->code - s->start;
1432 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, TRUE);
1435 stmt: BEQ (reg, reg) 1 {
1438 tree->is_jump = TRUE;
1439 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1440 offset = 6 + s->code - s->start;
1441 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, TRUE);
1444 stmt: BNE_UN (reg, reg) 1 {
1447 tree->is_jump = TRUE;
1448 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1449 offset = 6 + s->code - s->start;
1450 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
1453 stmt: BNE_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1456 tree->is_jump = TRUE;
1457 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1458 offset = 6 + s->code - s->start;
1459 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
1462 stmt: BGE (reg, reg) 1 {
1465 tree->is_jump = TRUE;
1466 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1467 offset = 6 + s->code - s->start;
1468 x86_branch32 (s->code, X86_CC_GE, tree->data.bb->addr - offset, TRUE);
1471 stmt: BGE (reg, CONST_I4) "MB_USE_OPT1(0)" {
1474 tree->is_jump = TRUE;
1475 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1476 offset = 6 + s->code - s->start;
1477 x86_branch32 (s->code, X86_CC_GE, tree->data.bb->addr - offset, TRUE);
1480 stmt: BGE_UN (reg, reg) 1 {
1483 tree->is_jump = TRUE;
1484 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1485 offset = 6 + s->code - s->start;
1486 x86_branch32 (s->code, X86_CC_GE, tree->data.bb->addr - offset, FALSE);
1489 stmt: BGE_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1492 tree->is_jump = TRUE;
1493 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1494 offset = 6 + s->code - s->start;
1495 x86_branch32 (s->code, X86_CC_GE, tree->data.bb->addr - offset, FALSE);
1498 stmt: BLE (reg, reg) 1 {
1501 tree->is_jump = TRUE;
1502 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1503 offset = 6 + s->code - s->start;
1504 x86_branch32 (s->code, X86_CC_LE, tree->data.bb->addr - offset, TRUE);
1507 stmt: BLE (reg, CONST_I4) "MB_USE_OPT1(0)" {
1510 tree->is_jump = TRUE;
1511 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1512 offset = 6 + s->code - s->start;
1513 x86_branch32 (s->code, X86_CC_LE, tree->data.bb->addr - offset, TRUE);
1516 stmt: BLE_UN (reg, reg) 1 {
1519 tree->is_jump = TRUE;
1520 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1521 offset = 6 + s->code - s->start;
1522 x86_branch32 (s->code, X86_CC_LE, tree->data.bb->addr - offset, FALSE);
1525 stmt: BLE_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1528 tree->is_jump = TRUE;
1529 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1530 offset = 6 + s->code - s->start;
1531 x86_branch32 (s->code, X86_CC_LE, tree->data.bb->addr - offset, FALSE);
1534 stmt: BRTRUE (reg) {
1537 tree->is_jump = TRUE;
1538 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
1539 offset = 6 + s->code - s->start;
1540 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, TRUE);
1543 stmt: BRFALSE (reg) {
1546 tree->is_jump = TRUE;
1547 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
1548 offset = 6 + s->code - s->start;
1549 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, TRUE);
1553 x86_breakpoint (s->code);
1559 if (tree->left->reg1 != X86_EAX)
1560 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1562 if (!tree->last_instr) {
1563 tree->is_jump = TRUE;
1564 offset = 5 + s->code - s->start;
1565 x86_jump32 (s->code, s->epilog - offset);
1572 if (!tree->last_instr) {
1573 tree->is_jump = TRUE;
1574 offset = 5 + s->code - s->start;
1575 x86_jump32 (s->code, s->epilog - offset);
1580 stmt: ARG_I4 (LDIND_I4 (addr)) {
1581 MBTree *at = tree->left->left;
1583 switch (at->data.ainfo.amode) {
1586 x86_push_mem (s->code, at->data.ainfo.offset);
1590 x86_push_membase (s->code, at->data.ainfo.basereg, at->data.ainfo.offset);
1593 x86_push_memindex (s->code, X86_NOBASEREG, at->data.ainfo.offset,
1594 at->data.ainfo.indexreg, at->data.ainfo.shift);
1597 x86_push_memindex (s->code, at->data.ainfo.basereg,
1598 at->data.ainfo.offset, at->data.ainfo.indexreg,
1599 at->data.ainfo.shift);
1604 stmt: ARG_I4 (LDIND_U4 (addr)) {
1605 MBTree *at = tree->left->left;
1607 switch (at->data.ainfo.amode) {
1610 x86_push_mem (s->code, at->data.ainfo.offset);
1614 x86_push_membase (s->code, at->data.ainfo.basereg, at->data.ainfo.offset);
1617 x86_push_memindex (s->code, X86_NOBASEREG, at->data.ainfo.offset,
1618 at->data.ainfo.indexreg, at->data.ainfo.shift);
1621 x86_push_memindex (s->code, at->data.ainfo.basereg,
1622 at->data.ainfo.offset, at->data.ainfo.indexreg,
1623 at->data.ainfo.shift);
1628 stmt: ARG_I4 (reg) {
1629 x86_push_reg (s->code, tree->left->reg1);
1630 PRINT_REG ("ARG_I4", tree->left->reg1);
1633 # fixme: we must free the allocated strings somewhere
1634 stmt: ARG_STRING (reg) {
1635 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
1636 x86_push_reg (s->code, X86_EAX);
1637 x86_push_reg (s->code, X86_ECX);
1638 x86_push_reg (s->code, X86_EDX);
1640 x86_push_reg (s->code, tree->left->reg1);
1641 x86_mov_reg_imm (s->code, X86_EAX, mono_string_to_utf8);
1642 x86_call_reg (s->code, X86_EAX);
1643 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
1645 x86_mov_membase_reg (s->code, X86_ESP, 12, X86_EAX, 4);
1647 x86_pop_reg (s->code, X86_EDX);
1648 x86_pop_reg (s->code, X86_ECX);
1649 x86_pop_reg (s->code, X86_EAX);
1652 stmt: ARG_I4 (ADDR_G) {
1653 x86_push_imm (s->code, tree->left->data.p);
1656 stmt: ARG_I4 (CONST_I4) "MB_USE_OPT1(0)" {
1657 x86_push_imm (s->code, tree->left->data.i);
1661 PRINT_REG ("THIS", tree->reg1);
1666 reg: CALL_I4 (this, reg) {
1667 MethodCallInfo *ci = tree->data.ci;
1669 int lreg = tree->left->reg1;
1670 int rreg = tree->right->reg1;
1672 if (lreg == treg || rreg == treg)
1674 if (lreg == treg || rreg == treg)
1676 if (lreg == treg || rreg == treg)
1677 g_assert_not_reached ();
1679 if (tree->left->op != MB_TERM_NOP) {
1680 g_assert (lreg >= 0);
1681 x86_push_reg (s->code, lreg);
1684 if (ci->vtype_num) {
1685 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1686 x86_lea_membase (s->code, treg, X86_EBP, offset);
1687 x86_push_reg (s->code, treg);
1690 x86_call_reg (s->code, rreg);
1693 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1695 PRINT_REG ("CALL_I4", tree->reg1);
1697 g_assert (tree->reg1 == X86_EAX);
1700 reg: CALL_I4 (this, ADDR_G) {
1701 MethodCallInfo *ci = tree->data.ci;
1702 int lreg = tree->left->reg1;
1710 if (tree->left->op != MB_TERM_NOP) {
1711 g_assert (lreg >= 0);
1712 x86_push_reg (s->code, lreg);
1715 if (ci->vtype_num) {
1716 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1717 x86_lea_membase (s->code, treg, X86_EBP, offset);
1718 x86_push_reg (s->code, treg);
1721 x86_call_code (s->code, tree->right->data.p);
1724 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1726 PRINT_REG ("CALL_I4", tree->reg1);
1728 g_assert (tree->reg1 == X86_EAX);
1731 reg: LDFTN (reg, INTF_ADDR) {
1732 int lreg = tree->left->reg1;
1734 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1735 x86_mov_reg_membase (s->code, lreg, lreg,
1736 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
1737 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
1738 x86_mov_reg_membase (s->code, tree->reg1, lreg, tree->right->data.m->slot << 2, 4);
1741 reg: CALL_I4 (this, INTF_ADDR) {
1742 MethodCallInfo *ci = tree->data.ci;
1743 int lreg = tree->left->reg1;
1749 if (tree->left->op != MB_TERM_NOP) {
1750 g_assert (lreg >= 0);
1751 x86_push_reg (s->code, lreg);
1754 if (ci->vtype_num) {
1755 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1756 x86_lea_membase (s->code, treg, X86_EBP, offset);
1757 x86_push_reg (s->code, treg);
1760 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1761 x86_mov_reg_membase (s->code, lreg, lreg,
1762 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
1763 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
1764 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
1767 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1769 PRINT_REG ("CALL_I4(INTERFACE)", tree->reg1);
1771 g_assert (tree->reg1 == X86_EAX);
1774 reg: LDFTN (reg, VFUNC_ADDR) {
1775 int lreg = tree->left->reg1;
1777 x86_mov_reg_membase (s->code, tree->reg1, lreg, 0, 4);
1779 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2), 4);
1782 reg: CALL_I4 (this, VFUNC_ADDR) {
1783 MethodCallInfo *ci = tree->data.ci;
1784 int lreg = tree->left->reg1;
1790 if (tree->left->op != MB_TERM_NOP) {
1791 g_assert (lreg >= 0);
1792 x86_push_reg (s->code, lreg);
1795 if (ci->vtype_num) {
1796 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1797 x86_lea_membase (s->code, treg, X86_EBP, offset);
1798 x86_push_reg (s->code, treg);
1801 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1802 x86_call_virtual (s->code, lreg,
1803 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
1806 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1808 PRINT_REG ("CALL_I4(VIRTUAL)", tree->reg1);
1810 g_assert (tree->reg1 == X86_EAX);
1813 stmt: CALL_VOID (this, ADDR_G) {
1814 MethodCallInfo *ci = tree->data.ci;
1815 int lreg = tree->left->reg1;
1823 if (tree->left->op != MB_TERM_NOP) {
1824 g_assert (lreg >= 0);
1825 x86_push_reg (s->code, lreg);
1828 if (ci->vtype_num) {
1829 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1830 x86_lea_membase (s->code, treg, X86_EBP, offset);
1831 x86_push_reg (s->code, treg);
1834 x86_call_code (s->code, tree->right->data.p);
1837 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1840 stmt: CALL_VOID (this, INTF_ADDR) {
1841 MethodCallInfo *ci = tree->data.ci;
1842 int lreg = tree->left->reg1;
1848 if (tree->left->op != MB_TERM_NOP) {
1849 g_assert (lreg >= 0);
1850 x86_push_reg (s->code, lreg);
1853 if (ci->vtype_num) {
1854 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1855 x86_lea_membase (s->code, treg, X86_EBP, offset);
1856 x86_push_reg (s->code, treg);
1859 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1860 x86_mov_reg_membase (s->code, lreg, lreg,
1861 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
1862 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
1863 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
1866 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1869 stmt: CALL_VOID (this, VFUNC_ADDR) {
1870 MethodCallInfo *ci = tree->data.ci;
1871 int lreg = tree->left->reg1;
1877 if (tree->left->op != MB_TERM_NOP) {
1878 g_assert (lreg >= 0);
1879 x86_push_reg (s->code, lreg);
1882 if (ci->vtype_num) {
1883 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1884 x86_lea_membase (s->code, treg, X86_EBP, offset);
1885 x86_push_reg (s->code, treg);
1888 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1889 x86_call_virtual (s->code, lreg,
1890 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
1893 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1896 stmt: SWITCH (reg) {
1898 guint32 *jt = (guint32 *)tree->data.p;
1900 tree->is_jump = TRUE;
1902 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, jt [0]);
1903 offset = 6 + (guint32)s->code;
1904 x86_branch32 (s->code, X86_CC_GE, jt [jt [0] + 1] - offset, FALSE);
1906 x86_mov_reg_memindex (s->code, X86_EAX, X86_NOBASEREG,
1907 tree->data.i + 4, tree->left->reg1, 2, 4);
1908 x86_jump_reg (s->code, X86_EAX);
1915 reg: CONV_I4 (lreg) {
1916 if (tree->reg1 != tree->left->reg1)
1917 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1920 reg: CONV_OVF_I4 (lreg){
1922 * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000
1924 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
1926 /* If the low word top bit is set, see if we are negative */
1927 x86_branch8 (s->code, X86_CC_LT, 14, TRUE);
1929 /* We are not negative (no top bit set, check for our top word to be zero */
1930 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
1931 x86_branch8 (s->code, X86_CC_EQ, 17, TRUE);
1933 /* throw exception */
1934 x86_push_imm (s->code, "OverflowException");
1935 x86_mov_reg_imm (s->code, X86_EAX, arch_get_throw_exception_by_name ());
1936 x86_call_reg (s->code, X86_EAX);
1938 /* our top bit is set, check that top word is 0xfffffff */
1939 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg2, 0xffffffff);
1941 /* nope, emit exception */
1942 x86_branch8 (s->code, X86_CC_NE, -17, TRUE);
1944 if (tree->reg1 != tree->left->reg1)
1945 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1948 reg: CONV_OVF_U4 (lreg) {
1949 /* Keep in sync with CONV_OVF_I4_UN below, they are the same on 32-bit machines */
1950 /* top word must be 0 */
1951 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
1952 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
1953 if (tree->reg1 != tree->left->reg1)
1954 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1957 reg: CONV_OVF_I4_UN (lreg) {
1958 /* Keep in sync with CONV_OVF_U4 above, they are the same on 32-bit machines */
1959 /* top word must be 0 */
1960 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
1961 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
1962 if (tree->reg1 != tree->left->reg1)
1963 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1969 x86_mov_reg_imm (s->code, tree->reg1, *((gint32 *)&tree->data.p));
1970 x86_mov_reg_imm (s->code, tree->reg2, *((gint32 *)&tree->data.p + 1));
1973 reg: CONV_I1 (lreg) {
1974 x86_alu_reg_imm (s->code, X86_AND, tree->left->reg1, 0xff);
1976 if (tree->reg1 != tree->left->reg1)
1977 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1980 lreg: CONV_I8 (CONST_I4) {
1981 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
1983 if (tree->left->data.i >= 0)
1984 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1986 x86_mov_reg_imm (s->code, tree->reg2, -1);
1989 lreg: CONV_I8 (reg) {
1992 if (tree->reg1 != tree->left->reg1)
1993 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1995 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
1996 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1997 x86_branch8 (s->code, X86_CC_GE, 5, TRUE);
1999 x86_mov_reg_imm (s->code, tree->reg2, -1);
2000 g_assert ((s->code - i1) == 5);
2003 lreg: CONV_U8 (CONST_I4) 1 {
2004 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
2005 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2008 lreg: CONV_OVF_U8 (CONST_I4) {
2009 if (tree->left->data.i < 0){
2010 x86_push_imm (s->code, "OverflowException");
2011 x86_mov_reg_imm (s->code, X86_EAX, arch_get_throw_exception_by_name ());
2012 x86_call_reg (s->code, X86_EAX);
2014 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
2015 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2019 lreg: CONV_OVF_I8_UN (CONST_I4) {
2020 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
2021 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2024 lreg: CONV_OVF_U8 (reg) {
2025 x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
2026 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
2028 if (tree->reg1 != tree->left->reg1)
2029 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2030 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2033 lreg: CONV_OVF_I8_UN (reg) {
2034 /* Convert uint value into int64, we pass everything */
2035 if (tree->reg1 != tree->left->reg1)
2036 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2037 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
2040 stmt: STIND_I8 (addr, lreg) {
2042 switch (tree->left->data.ainfo.amode) {
2045 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
2046 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset + 4, tree->right->reg2, 4);
2050 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
2051 tree->left->data.ainfo.offset, tree->right->reg1, 4);
2052 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
2053 tree->left->data.ainfo.offset + 4, tree->right->reg2, 4);
2056 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
2057 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2058 tree->right->reg1, 4);
2059 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset + 4,
2060 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2061 tree->right->reg2, 4);
2064 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
2065 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2066 tree->right->reg1, 4);
2067 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset + 4,
2068 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2069 tree->right->reg2, 4);
2075 # an addr can use two address register (base and index register). The must take care
2076 # that we do not override them (thus the use of x86_lea)
2077 lreg: LDIND_I8 (addr) {
2079 switch (tree->left->data.ainfo.amode) {
2082 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
2083 x86_mov_reg_mem (s->code, tree->reg2, tree->left->data.ainfo.offset + 4, 4);
2087 x86_lea_membase (s->code, tree->reg2, tree->left->data.ainfo.basereg,
2088 tree->left->data.ainfo.offset);
2089 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
2090 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
2093 x86_lea_memindex (s->code, tree->reg2, X86_NOBASEREG, tree->left->data.ainfo.offset,
2094 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift);
2095 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
2096 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
2099 x86_lea_memindex (s->code, tree->reg2, tree->left->data.ainfo.basereg,
2100 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
2101 tree->left->data.ainfo.shift);
2102 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
2103 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
2106 PRINT_REG ("LDIND_I8_0", tree->reg1);
2107 PRINT_REG ("LDIND_I8_1", tree->reg2);
2110 lreg: SHR (lreg, CONST_I4) {
2111 if (tree->right->data.i < 32) {
2112 x86_shrd_reg_imm (s->code, tree->left->reg1, tree->left->reg2, tree->right->data.i);
2113 x86_shift_reg_imm (s->code, X86_SAR, tree->left->reg2, tree->right->data.i);
2114 if (tree->reg1 != tree->left->reg1)
2115 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2116 if (tree->reg2 != tree->left->reg2)
2117 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2118 } else if (tree->right->data.i < 64) {
2119 if (tree->reg1 != tree->left->reg2)
2120 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg2, 4);
2121 if (tree->reg2 != tree->left->reg2)
2122 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2123 x86_shift_reg_imm (s->code, X86_SAR, tree->reg2, 31);
2124 x86_shift_reg_imm (s->code, X86_SAR, tree->reg1, (tree->right->data.i - 32));
2125 } /* else unspecified result */
2128 lreg: SHR_UN (lreg, CONST_I4) {
2129 if (tree->right->data.i < 32) {
2130 x86_shrd_reg_imm (s->code, tree->left->reg1, tree->left->reg2, tree->right->data.i);
2131 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg2, tree->right->data.i);
2132 if (tree->reg1 != tree->left->reg1)
2133 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2134 if (tree->reg2 != tree->left->reg2)
2135 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2136 } else if (tree->right->data.i < 64) {
2137 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg2, 4);
2138 x86_shift_reg_imm (s->code, X86_SHR, tree->reg1, (tree->right->data.i - 32));
2139 x86_mov_reg_imm (s->code, tree->reg2, 0);
2140 } /* else unspecified result */
2143 lreg: SHR (lreg, reg) {
2144 guint8 *start = s->code;
2147 tree->is_jump = TRUE;
2149 if (tree->right->reg1 != X86_ECX)
2150 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
2152 for (i = 0; i < 2; i ++) {
2154 x86_shrd_reg (s->code, tree->left->reg1, tree->left->reg2);
2155 x86_shift_reg (s->code, X86_SAR, tree->left->reg2);
2156 x86_test_reg_imm (s->code, X86_ECX, 32);
2157 o1 = 2 + s->code - s->start;
2158 x86_branch8 (s->code, X86_CC_EQ, o2 - o1, FALSE);
2159 x86_mov_reg_reg (s->code, tree->left->reg1, tree->left->reg2, 4);
2160 x86_shift_reg_imm (s->code, X86_SAR, tree->reg2, 31);
2161 o2 = s->code - s->start;
2164 if (tree->reg1 != tree->left->reg1)
2165 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2166 if (tree->reg2 != tree->left->reg2)
2167 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2170 lreg: SHR_UN (lreg, reg) {
2171 guint8 *start = s->code;
2174 tree->is_jump = TRUE;
2176 if (tree->right->reg1 != X86_ECX)
2177 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
2179 for (i = 0; i < 2; i ++) {
2181 x86_shrd_reg (s->code, tree->left->reg1, tree->left->reg2);
2182 x86_shift_reg (s->code, X86_SHR, tree->left->reg2);
2183 x86_test_reg_imm (s->code, X86_ECX, 32);
2184 o1 = 2 + s->code - s->start;
2185 x86_branch8 (s->code, X86_CC_EQ, o2 - o1, FALSE);
2186 x86_mov_reg_reg (s->code, tree->left->reg1, tree->left->reg2, 4);
2187 x86_shift_reg_imm (s->code, X86_SHR, tree->reg2, 31);
2188 o2 = s->code - s->start;
2191 if (tree->reg1 != tree->left->reg1)
2192 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2193 if (tree->reg2 != tree->left->reg2)
2194 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2197 lreg: SHL (lreg, CONST_I4) {
2198 if (tree->right->data.i < 32) {
2199 x86_shld_reg_imm (s->code, tree->left->reg2, tree->left->reg1, tree->right->data.i);
2200 x86_shift_reg_imm (s->code, X86_SHL, tree->left->reg1, tree->right->data.i);
2201 if (tree->reg1 != tree->left->reg1)
2202 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2203 if (tree->reg2 != tree->left->reg2)
2204 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2205 } else if (tree->right->data.i < 64) {
2206 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg1, 4);
2207 x86_shift_reg_imm (s->code, X86_SHL, tree->reg2, (tree->right->data.i - 32));
2208 x86_alu_reg_reg (s->code, X86_XOR, tree->reg1, tree->reg1);
2209 } /* else unspecified result */
2212 lreg: SHL (lreg, reg) {
2213 guint8 *start = s->code;
2216 tree->is_jump = TRUE;
2218 if (tree->right->reg1 != X86_ECX)
2219 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
2221 for (i = 0; i < 2; i ++) {
2223 x86_shld_reg (s->code, tree->left->reg2, tree->left->reg1);
2224 x86_shift_reg (s->code, X86_SHL, tree->left->reg1);
2225 x86_test_reg_imm (s->code, X86_ECX, 32);
2226 o1 = 2 + s->code - s->start;
2227 x86_branch8 (s->code, X86_CC_EQ, o2 - o1, FALSE);
2228 x86_mov_reg_reg (s->code, tree->left->reg2, tree->left->reg1, 4);
2229 x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->left->reg1);
2230 o2 = s->code - s->start;
2233 if (tree->reg1 != tree->left->reg1)
2234 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2235 if (tree->reg2 != tree->left->reg2)
2236 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2239 lreg: ADD (lreg, lreg) {
2240 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
2241 x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
2243 if (tree->reg1 != tree->left->reg1)
2244 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2245 if (tree->reg2 != tree->left->reg2)
2246 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2249 lreg: ADD_OVF (lreg, lreg) {
2250 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
2251 x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
2252 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
2254 if (tree->reg1 != tree->left->reg1)
2255 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2256 if (tree->reg2 != tree->left->reg2)
2257 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2260 lreg: ADD_OVF_UN (lreg, lreg) {
2261 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
2262 x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
2263 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
2265 if (tree->reg1 != tree->left->reg1)
2266 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2267 if (tree->reg2 != tree->left->reg2)
2268 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2271 lreg: SUB (lreg, lreg) {
2272 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
2273 x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
2275 if (tree->reg1 != tree->left->reg1)
2276 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2277 if (tree->reg2 != tree->left->reg2)
2278 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2281 lreg: SUB_OVF (lreg, lreg) {
2282 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
2283 x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
2284 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
2286 if (tree->reg1 != tree->left->reg1)
2287 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2288 if (tree->reg2 != tree->left->reg2)
2289 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2292 lreg: SUB_OVF_UN (lreg, lreg) {
2293 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
2294 x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
2295 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
2297 if (tree->reg1 != tree->left->reg1)
2298 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2299 if (tree->reg2 != tree->left->reg2)
2300 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2303 lreg: AND (lreg, lreg) {
2304 x86_alu_reg_reg (s->code, X86_AND, tree->left->reg1, tree->right->reg1);
2305 x86_alu_reg_reg (s->code, X86_AND, tree->left->reg2, tree->right->reg2);
2307 if (tree->reg1 != tree->left->reg1)
2308 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2309 if (tree->reg2 != tree->left->reg2)
2310 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2313 lreg: OR (lreg, lreg) {
2314 x86_alu_reg_reg (s->code, X86_OR, tree->left->reg1, tree->right->reg1);
2315 x86_alu_reg_reg (s->code, X86_OR, tree->left->reg2, tree->right->reg2);
2317 if (tree->reg1 != tree->left->reg1)
2318 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2319 if (tree->reg2 != tree->left->reg2)
2320 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2324 if (tree->reg1 != tree->left->reg1)
2325 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2326 if (tree->reg2 != tree->left->reg2)
2327 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2329 x86_neg_reg (s->code, tree->reg1);
2330 x86_alu_reg_imm (s->code, X86_ADC, tree->reg2, 0);
2331 x86_neg_reg (s->code, tree->reg2);
2335 if (tree->reg1 != tree->left->reg1)
2336 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2337 if (tree->reg2 != tree->left->reg2)
2338 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2340 x86_not_reg (s->code, tree->reg1);
2341 x86_not_reg (s->code, tree->reg2);
2344 lreg: MUL (lreg, lreg) {
2345 if (mono_regset_reg_used (s->rs, X86_ECX))
2346 x86_push_reg (s->code, X86_ECX);
2348 x86_push_reg (s->code, tree->right->reg2);
2349 x86_push_reg (s->code, tree->right->reg1);
2350 x86_push_reg (s->code, tree->left->reg2);
2351 x86_push_reg (s->code, tree->left->reg1);
2352 x86_mov_reg_imm (s->code, X86_EAX, mono_llmult);
2353 x86_call_reg (s->code, X86_EAX);
2354 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2356 if (mono_regset_reg_used (s->rs, X86_ECX))
2357 x86_pop_reg (s->code, X86_ECX);
2359 g_assert (tree->reg1 == X86_EAX &&
2360 tree->reg2 == X86_EDX);
2363 lreg: MUL_OVF_UN (lreg, lreg) {
2364 if (mono_regset_reg_used (s->rs, X86_ECX))
2365 x86_push_reg (s->code, X86_ECX);
2367 x86_push_reg (s->code, tree->right->reg2);
2368 x86_push_reg (s->code, tree->right->reg1);
2369 x86_push_reg (s->code, tree->left->reg2);
2370 x86_push_reg (s->code, tree->left->reg1);
2371 /* pass a pointer to store the resulting exception -
2372 * ugly, but it works */
2373 x86_push_reg (s->code, X86_ESP);
2374 x86_mov_reg_imm (s->code, X86_EAX, mono_llmult_ovf_un);
2375 x86_call_reg (s->code, X86_EAX);
2376 x86_mov_reg_membase (s->code, X86_ECX, X86_ESP, 4, 4);
2377 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
2378 x86_alu_reg_imm (s->code, X86_CMP, X86_ECX, 0);
2380 /* cond. emit exception */
2381 x86_branch8 (s->code, X86_CC_EQ, 9, FALSE);
2382 x86_push_reg (s->code, X86_ECX);
2383 x86_mov_reg_imm (s->code, X86_EAX, arch_get_throw_exception ());
2384 x86_call_reg (s->code, X86_EAX);
2386 if (mono_regset_reg_used (s->rs, X86_ECX))
2387 x86_pop_reg (s->code, X86_ECX);
2389 g_assert (tree->reg1 == X86_EAX &&
2390 tree->reg2 == X86_EDX);
2393 lreg: DIV (lreg, lreg) {
2394 if (mono_regset_reg_used (s->rs, X86_ECX))
2395 x86_push_reg (s->code, X86_ECX);
2397 x86_push_reg (s->code, tree->right->reg2);
2398 x86_push_reg (s->code, tree->right->reg1);
2399 x86_push_reg (s->code, tree->left->reg2);
2400 x86_push_reg (s->code, tree->left->reg1);
2401 x86_mov_reg_imm (s->code, X86_EAX, mono_lldiv);
2402 x86_call_reg (s->code, X86_EAX);
2403 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2405 if (mono_regset_reg_used (s->rs, X86_ECX))
2406 x86_pop_reg (s->code, X86_ECX);
2408 g_assert (tree->reg1 == X86_EAX &&
2409 tree->reg2 == X86_EDX);
2412 lreg: REM (lreg, lreg) {
2413 if (mono_regset_reg_used (s->rs, X86_ECX))
2414 x86_push_reg (s->code, X86_ECX);
2416 x86_push_reg (s->code, tree->right->reg2);
2417 x86_push_reg (s->code, tree->right->reg1);
2418 x86_push_reg (s->code, tree->left->reg2);
2419 x86_push_reg (s->code, tree->left->reg1);
2420 x86_mov_reg_imm (s->code, X86_EAX, mono_llrem);
2421 x86_call_reg (s->code, X86_EAX);
2422 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2424 if (mono_regset_reg_used (s->rs, X86_ECX))
2425 x86_pop_reg (s->code, X86_ECX);
2427 g_assert (tree->reg1 == X86_EAX &&
2428 tree->reg2 == X86_EDX);
2431 lreg: DIV_UN (lreg, lreg) {
2432 if (mono_regset_reg_used (s->rs, X86_ECX))
2433 x86_push_reg (s->code, X86_ECX);
2435 x86_push_reg (s->code, tree->right->reg2);
2436 x86_push_reg (s->code, tree->right->reg1);
2437 x86_push_reg (s->code, tree->left->reg2);
2438 x86_push_reg (s->code, tree->left->reg1);
2439 x86_mov_reg_imm (s->code, X86_EAX, mono_lldiv_un);
2440 x86_call_reg (s->code, X86_EAX);
2441 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2443 if (mono_regset_reg_used (s->rs, X86_ECX))
2444 x86_pop_reg (s->code, X86_ECX);
2446 g_assert (tree->reg1 == X86_EAX &&
2447 tree->reg2 == X86_EDX);
2450 lreg: REM_UN (lreg, lreg) {
2451 if (mono_regset_reg_used (s->rs, X86_ECX))
2452 x86_push_reg (s->code, X86_ECX);
2454 x86_push_reg (s->code, tree->right->reg2);
2455 x86_push_reg (s->code, tree->right->reg1);
2456 x86_push_reg (s->code, tree->left->reg2);
2457 x86_push_reg (s->code, tree->left->reg1);
2458 x86_mov_reg_imm (s->code, X86_EAX, mono_llrem_un);
2459 x86_call_reg (s->code, X86_EAX);
2460 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2462 if (mono_regset_reg_used (s->rs, X86_ECX))
2463 x86_pop_reg (s->code, X86_ECX);
2465 g_assert (tree->reg1 == X86_EAX &&
2466 tree->reg2 == X86_EDX);
2469 lreg: CALL_I8 (this, ADDR_G) {
2470 MethodCallInfo *ci = tree->data.ci;
2471 int lreg = tree->left->reg1;
2479 if (tree->left->op != MB_TERM_NOP) {
2480 g_assert (lreg >= 0);
2481 x86_push_reg (s->code, lreg);
2484 if (ci->vtype_num) {
2485 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
2486 x86_lea_membase (s->code, treg, X86_EBP, offset);
2487 x86_push_reg (s->code, treg);
2490 x86_call_code (s->code, tree->right->data.p);
2493 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
2495 g_assert (tree->reg1 == X86_EAX);
2496 g_assert (tree->reg2 == X86_EDX);
2499 lreg: CALL_I8 (this, VFUNC_ADDR) {
2500 MethodCallInfo *ci = tree->data.ci;
2501 int lreg = tree->left->reg1;
2507 if (tree->left->op != MB_TERM_NOP) {
2508 g_assert (lreg >= 0);
2509 x86_push_reg (s->code, lreg);
2512 if (ci->vtype_num) {
2513 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
2514 x86_lea_membase (s->code, treg, X86_EBP, offset);
2515 x86_push_reg (s->code, treg);
2518 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2519 x86_call_virtual (s->code, lreg,
2520 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
2523 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
2525 PRINT_REG ("CALL0_I8(VIRTUAL)", tree->reg1);
2526 PRINT_REG ("CALL1_I8(VIRTUAL)", tree->reg2);
2528 g_assert (tree->reg1 == X86_EAX);
2529 g_assert (tree->reg2 == X86_EDX);
2535 if (tree->left->reg1 != X86_EAX) {
2536 if (tree->left->reg2 != X86_EAX) {
2537 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
2538 if (tree->left->reg2 != X86_EDX)
2539 x86_mov_reg_reg (s->code, X86_EDX, tree->left->reg2, 4);
2541 x86_mov_reg_reg (s->code, X86_ECX, tree->left->reg2, 4);
2542 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
2543 x86_mov_reg_reg (s->code, X86_EDX, X86_ECX, 4);
2545 } else if (tree->left->reg2 != X86_EDX) {
2546 x86_mov_reg_reg (s->code, X86_EDX, tree->left->reg2, 4);
2549 if (!tree->last_instr) {
2550 tree->is_jump = TRUE;
2551 offset = 5 + s->code - s->start;
2552 x86_jump32 (s->code, s->epilog - offset);
2557 stmt: ARG_I8 (lreg) {
2558 x86_push_reg (s->code, tree->left->reg2);
2559 x86_push_reg (s->code, tree->left->reg1);
2562 reg: CEQ (lreg, lreg) {
2563 guint8 *start = s->code;
2566 tree->is_jump = TRUE;
2568 for (i = 0; i < 2; i ++) {
2570 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2571 o1 = 2 + s->code - s->start;
2572 x86_branch8 (s->code, X86_CC_NE, o2 - o1, FALSE);
2573 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2574 o2 = s->code - s->start;
2575 x86_set_reg (s->code, X86_CC_EQ, tree->reg1, FALSE);
2576 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
2580 reg: CLT (lreg, lreg) {
2581 guint8 *start = s->code;
2582 gint32 o1, o2, o3, o4, o5, i;
2584 tree->is_jump = TRUE;
2586 for (i = 0; i < 2; i ++) {
2588 x86_alu_reg_reg (s->code, X86_XOR, tree->reg1, tree->reg1);
2589 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2590 o1 = 2 + s->code - s->start;
2591 x86_branch8 (s->code, X86_CC_GT, o5 - o1, TRUE);
2592 o2 = 2 + s->code - s->start;
2593 x86_branch8 (s->code, X86_CC_NE, o4 - o2, TRUE);
2594 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2595 o3 = 2 + s->code - s->start;
2596 x86_branch8 (s->code, X86_CC_LE, o4 - o3, FALSE);
2597 o5 = s->code - s->start;
2598 x86_mov_reg_imm (s->code, tree->reg1, 1);
2599 o4 = s->code - s->start;
2603 stmt: BEQ (lreg, lreg) {
2604 guint8 *start = s->code;
2607 tree->is_jump = TRUE;
2609 for (i = 0; i < 2; i ++) {
2611 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2612 o1 = 2 + s->code - s->start;
2613 x86_branch8 (s->code, X86_CC_NE, o2 - o1, FALSE);
2614 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2615 o2 = 6 + s->code - s->start;
2616 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - o2, TRUE);
2620 stmt: BNE_UN (lreg, lreg) {
2623 tree->is_jump = TRUE;
2625 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2626 offset = 6 + s->code - s->start;
2627 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
2628 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2629 offset = 6 + s->code - s->start;
2630 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
2633 stmt: BGE (lreg, lreg) {
2634 guint8 *start = s->code;
2635 gint32 o1, o2, oe, i;
2637 tree->is_jump = TRUE;
2639 for (i = 0; i < 2; i ++) {
2641 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2642 o1 = 6 + s->code - s->start;
2643 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - o1, TRUE);
2644 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2645 o2 = 2 + s->code - s->start;
2646 x86_branch8 (s->code, X86_CC_NE, oe - o2, TRUE);
2647 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2648 oe = 6 + s->code - s->start;
2649 x86_branch32 (s->code, X86_CC_GE, tree->data.bb->addr - oe, FALSE);
2653 stmt: BGE_UN (lreg, lreg) {
2654 guint8 *start = s->code;
2655 gint32 o1, o2, oe, i;
2657 tree->is_jump = TRUE;
2659 for (i = 0; i < 2; i ++) {
2661 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2662 o1 = 6 + s->code - s->start;
2663 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - o1, FALSE);
2664 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2665 o2 = 2 + s->code - s->start;
2666 x86_branch8 (s->code, X86_CC_NE, oe - o2, FALSE);
2667 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2668 oe = 6 + s->code - s->start;
2669 x86_branch32 (s->code, X86_CC_GE, tree->data.bb->addr - oe, FALSE);
2673 stmt: BGT (lreg, lreg) {
2674 guint8 *start = s->code;
2675 gint32 o1, o2, oe, i;
2677 tree->is_jump = TRUE;
2679 for (i = 0; i < 2; i ++) {
2681 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2682 o1 = 6 + s->code - s->start;
2683 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - o1, TRUE);
2684 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2685 o2 = 2 + s->code - s->start;
2686 x86_branch8 (s->code, X86_CC_NE, oe - o2, TRUE);
2687 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2688 oe = 6 + s->code - s->start;
2689 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - oe, FALSE);
2693 stmt: BGT_UN (lreg, lreg) {
2694 guint8 *start = s->code;
2695 gint32 o1, o2, oe, i;
2697 tree->is_jump = TRUE;
2699 for (i = 0; i < 2; i ++) {
2701 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2702 o1 = 6 + s->code - s->start;
2703 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - o1, FALSE);
2704 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2705 o2 = 2 + s->code - s->start;
2706 x86_branch8 (s->code, X86_CC_NE, oe - o2, FALSE);
2707 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2708 oe = 6 + s->code - s->start;
2709 x86_branch32 (s->code, X86_CC_GT, tree->data.bb->addr - oe, FALSE);
2713 stmt: BLT (lreg, lreg) {
2714 guint8 *start = s->code;
2715 gint32 o1, o2, oe, i;
2717 tree->is_jump = TRUE;
2719 for (i = 0; i < 2; i ++) {
2721 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2722 o1 = 6 + s->code - s->start;
2723 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - o1, TRUE);
2724 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2725 o2 = 2 + s->code - s->start;
2726 x86_branch8 (s->code, X86_CC_NE, oe - o2, TRUE);
2727 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2728 oe = 6 + s->code - s->start;
2729 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - oe, FALSE);
2733 stmt: BLT_UN (lreg, lreg) {
2734 guint8 *start = s->code;
2735 gint32 o1, o2, oe, i;
2737 tree->is_jump = TRUE;
2739 for (i = 0; i < 2; i ++) {
2741 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2742 o1 = 6 + s->code - s->start;
2743 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - o1, FALSE);
2744 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2745 o2 = 2 + s->code - s->start;
2746 x86_branch8 (s->code, X86_CC_NE, oe - o2, FALSE);
2747 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2748 oe = 6 + s->code - s->start;
2749 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - oe, FALSE);
2753 stmt: BLE (lreg, lreg) {
2754 guint8 *start = s->code;
2755 gint32 o1, o2, oe, i;
2757 tree->is_jump = TRUE;
2759 for (i = 0; i < 2; i ++) {
2761 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2762 o1 = 6 + s->code - s->start;
2763 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - o1, TRUE);
2764 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2765 o2 = 2 + s->code - s->start;
2766 x86_branch8 (s->code, X86_CC_NE, oe - o2, TRUE);
2767 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2768 oe = 6 + s->code - s->start;
2769 x86_branch32 (s->code, X86_CC_LE, tree->data.bb->addr - oe, FALSE);
2773 stmt: BLE_UN (lreg, lreg) {
2774 guint8 *start = s->code;
2775 gint32 o1, o2, oe, i;
2777 tree->is_jump = TRUE;
2779 for (i = 0; i < 2; i ++) {
2781 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2782 o1 = 6 + s->code - s->start;
2783 x86_branch32 (s->code, X86_CC_LT, tree->data.bb->addr - o1, FALSE);
2784 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2785 o2 = 2 + s->code - s->start;
2786 x86_branch8 (s->code, X86_CC_NE, oe - o2, FALSE);
2787 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2788 oe = 6 + s->code - s->start;
2789 x86_branch32 (s->code, X86_CC_LE, tree->data.bb->addr - oe, FALSE);
2796 #stmt: STLOC (CONV_I4 (freg)) {
2798 # x86_fist_pop_membase (s->code, X86_EBP, tree->data.i, FALSE);
2801 reg: CONV_I4 (freg) {
2802 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
2803 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
2804 x86_pop_reg (s->code, tree->reg1);
2807 reg: CEQ (freg, freg) {
2808 int treg = tree->reg1;
2810 if (treg != X86_EAX)
2811 x86_push_reg (s->code, X86_EAX); // save EAX
2813 x86_fcompp (s->code);
2814 x86_fnstsw (s->code);
2815 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
2816 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
2817 x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
2818 x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
2820 if (treg != X86_EAX)
2821 x86_pop_reg (s->code, X86_EAX); // save EAX
2824 freg: CONV_R8 (freg) {
2828 freg: CONV_R4 (freg) {
2829 /* fixme: nothing to do ??*/
2832 freg: CONV_R8 (LDIND_I4 (ADDR_G)) {
2833 x86_fild (s->code, tree->left->left->data.p, FALSE);
2836 freg: CONV_R8 (reg) {
2837 /* I found no direct way to move an integer register to
2838 * the floating point stack, so we need to store the register
2841 x86_push_reg (s->code, tree->left->reg1);
2842 x86_fild_membase (s->code, X86_ESP, 0, FALSE);
2843 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
2846 freg: CONV_R8 (lreg) {
2847 /* I found no direct way to move an integer register to
2848 * the floating point stack, so we need to store the register
2851 x86_push_reg (s->code, tree->left->reg2);
2852 x86_push_reg (s->code, tree->left->reg1);
2853 x86_fild_membase (s->code, X86_ESP, 0, TRUE);
2854 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
2857 freg: CONV_R4 (reg) {
2858 /* I found no direct way to move an integer register to
2859 * the floating point stack, so we need to store the register
2862 x86_push_reg (s->code, tree->left->reg1);
2863 x86_fild_membase (s->code, X86_ESP, 0, FALSE);
2864 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
2868 float f = *(float *)tree->data.p;
2875 x86_fld (s->code, tree->data.p, FALSE);
2879 double d = *(double *)tree->data.p;
2886 x86_fld (s->code, tree->data.p, TRUE);
2889 freg: LDIND_R4 (reg) {
2890 x86_fld_membase (s->code, tree->left->reg1, 0, FALSE);
2893 freg: LDIND_R8 (reg) {
2894 x86_fld_membase (s->code, tree->left->reg1, 0, TRUE);
2897 freg: ADD (freg, freg) {
2898 x86_fp_op_reg (s->code, X86_FADD, 1, TRUE);
2901 freg: SUB (freg, freg) {
2902 x86_fp_op_reg (s->code, X86_FSUB, 1, TRUE);
2905 freg: MUL (freg, freg) {
2906 x86_fp_op_reg (s->code, X86_FMUL, 1, TRUE);
2909 freg: DIV (freg, freg) {
2910 x86_fp_op_reg (s->code, X86_FDIV, 1, TRUE);
2913 #freg: REM (freg, freg) {
2914 # this does not work, since it does not pop a value from the stack,
2915 # and we need to test if the instruction is ready
2916 # x86_fprem1 (s->code);
2925 stmt: STIND_R4 (ADDR_L, freg) {
2926 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->left->data.i).offset;
2927 x86_fst_membase (s->code, X86_EBP, offset, FALSE, TRUE);
2930 stmt: STIND_R4 (reg, freg) {
2931 x86_fst_membase (s->code, tree->left->reg1, 0, FALSE, TRUE);
2934 stmt: STIND_R8 (ADDR_L, freg) {
2935 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->left->data.i).offset;
2936 x86_fst_membase (s->code, X86_EBP, offset, TRUE, TRUE);
2939 stmt: STIND_R8 (reg, freg) {
2940 x86_fst_membase (s->code, tree->left->reg1, 0, TRUE, TRUE);
2943 stmt: ARG_R4 (freg) {
2944 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
2945 x86_fst_membase (s->code, X86_ESP, 0, FALSE, TRUE);
2948 stmt: ARG_R8 (freg) {
2949 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
2950 x86_fst_membase (s->code, X86_ESP, 0, TRUE, TRUE);
2953 # fixme: we need to implement unordered and ordered compares
2955 stmt: BEQ (freg, freg) {
2958 tree->is_jump = TRUE;
2959 x86_fcompp (s->code);
2960 x86_fnstsw (s->code);
2961 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
2962 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
2963 offset = 6 + s->code - s->start;
2964 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, TRUE);
2967 stmt: BNE_UN (freg, freg) {
2970 tree->is_jump = TRUE;
2971 x86_fcompp (s->code);
2972 x86_fnstsw (s->code);
2973 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
2974 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
2975 offset = 6 + s->code - s->start;
2976 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
2979 stmt: BLT (freg, freg) {
2982 tree->is_jump = TRUE;
2983 x86_fcompp (s->code);
2984 x86_fnstsw (s->code);
2985 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
2986 offset = 6 + s->code - s->start;
2987 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, FALSE);
2990 stmt: BLT_UN (freg, freg) {
2993 tree->is_jump = TRUE;
2994 x86_fcompp (s->code);
2995 x86_fnstsw (s->code);
2996 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
2997 offset = 6 + s->code - s->start;
2998 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, FALSE);
3001 stmt: BGE (freg, freg) {
3004 tree->is_jump = TRUE;
3005 x86_fcompp (s->code);
3006 x86_fnstsw (s->code);
3007 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3008 offset = 6 + s->code - s->start;
3009 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
3012 stmt: BGE_UN (freg, freg) {
3015 tree->is_jump = TRUE;
3016 x86_fcompp (s->code);
3017 x86_fnstsw (s->code);
3018 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3019 offset = 6 + s->code - s->start;
3020 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
3023 stmt: BGT (freg, freg) {
3026 tree->is_jump = TRUE;
3027 x86_fcompp (s->code);
3028 x86_fnstsw (s->code);
3029 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3030 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3031 offset = 6 + s->code - s->start;
3032 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, FALSE);
3035 stmt: BGT_UN (freg, freg) {
3038 tree->is_jump = TRUE;
3039 x86_fcompp (s->code);
3040 x86_fnstsw (s->code);
3041 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3042 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3043 offset = 6 + s->code - s->start;
3044 x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, FALSE);
3047 stmt: BLE (freg, freg) {
3050 tree->is_jump = TRUE;
3051 x86_fcompp (s->code);
3052 x86_fnstsw (s->code);
3053 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3054 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3055 offset = 6 + s->code - s->start;
3056 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
3059 stmt: BLE_UN (freg, freg) {
3062 tree->is_jump = TRUE;
3063 x86_fcompp (s->code);
3064 x86_fnstsw (s->code);
3065 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3066 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3067 offset = 6 + s->code - s->start;
3068 x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
3071 freg: CALL_R8 (this, ADDR_G) {
3072 MethodCallInfo *ci = tree->data.ci;
3073 int lreg = tree->left->reg1;
3081 if (tree->left->op != MB_TERM_NOP) {
3082 g_assert (lreg >= 0);
3083 x86_push_reg (s->code, lreg);
3086 if (ci->vtype_num) {
3087 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
3088 x86_lea_membase (s->code, treg, X86_EBP, offset);
3089 x86_push_reg (s->code, treg);
3092 x86_call_code (s->code, tree->right->data.p);
3095 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
3098 freg: CALL_R8 (this, INTF_ADDR) {
3099 MethodCallInfo *ci = tree->data.ci;
3100 int lreg = tree->left->reg1;
3106 if (tree->left->op != MB_TERM_NOP) {
3107 g_assert (lreg >= 0);
3108 x86_push_reg (s->code, lreg);
3111 if (ci->vtype_num) {
3112 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
3113 x86_lea_membase (s->code, treg, X86_EBP, offset);
3114 x86_push_reg (s->code, treg);
3117 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
3118 x86_mov_reg_membase (s->code, lreg, lreg,
3119 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
3120 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
3121 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
3124 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
3127 freg: CALL_R8 (this, VFUNC_ADDR) {
3128 MethodCallInfo *ci = tree->data.ci;
3129 int lreg = tree->left->reg1;
3135 if (tree->left->op != MB_TERM_NOP) {
3136 g_assert (lreg >= 0);
3137 x86_push_reg (s->code, lreg);
3140 if (ci->vtype_num) {
3141 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
3142 x86_lea_membase (s->code, treg, X86_EBP, offset);
3143 x86_push_reg (s->code, treg);
3146 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
3147 x86_call_virtual (s->code, lreg,
3148 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
3151 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
3157 if (!tree->last_instr) {
3158 tree->is_jump = TRUE;
3159 offset = 5 + s->code - s->start;
3160 x86_jump32 (s->code, s->epilog - offset);
3164 # support for value types
3166 reg: LDIND_OBJ (reg) {
3167 if (tree->left->reg1 != tree->reg1)
3168 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3171 stmt: STIND_OBJ (reg, reg) {
3172 x86_push_reg (s->code, X86_EAX);
3173 x86_push_reg (s->code, X86_EDX);
3174 x86_push_reg (s->code, X86_ECX);
3176 g_assert (tree->data.i > 0);
3177 x86_push_imm (s->code, tree->data.i);
3178 x86_push_reg (s->code, tree->right->reg1);
3179 x86_push_reg (s->code, tree->left->reg1);
3180 x86_mov_reg_imm (s->code, X86_EAX, MEMCOPY);
3181 x86_call_reg (s->code, X86_EAX);
3182 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
3184 x86_pop_reg (s->code, X86_ECX);
3185 x86_pop_reg (s->code, X86_EDX);
3186 x86_pop_reg (s->code, X86_EAX);
3189 stmt: ARG_OBJ (CONST_I4) {
3190 x86_push_imm (s->code, tree->left->data.i);
3193 stmt: ARG_OBJ (reg) {
3194 int size = tree->data.i;
3197 g_assert (size > 0);
3202 /* reserve space for the argument */
3203 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);
3205 x86_push_reg (s->code, X86_EAX);
3206 x86_push_reg (s->code, X86_EDX);
3207 x86_push_reg (s->code, X86_ECX);
3209 x86_push_imm (s->code, size);
3210 x86_push_reg (s->code, tree->left->reg1);
3211 x86_lea_membase (s->code, X86_EAX, X86_ESP, 5*4);
3212 x86_push_reg (s->code, X86_EAX);
3214 x86_mov_reg_imm (s->code, X86_EAX, MEMCOPY);
3215 x86_call_reg (s->code, X86_EAX);
3216 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
3218 x86_pop_reg (s->code, X86_ECX);
3219 x86_pop_reg (s->code, X86_EDX);
3220 x86_pop_reg (s->code, X86_EAX);
3223 stmt: RET_OBJ (reg) {
3225 int size = tree->data.i;
3227 x86_push_imm (s->code, size);
3228 x86_push_reg (s->code, tree->left->reg1);
3229 x86_push_membase (s->code, X86_EBP, 8);
3231 x86_mov_reg_imm (s->code, X86_EAX, MEMCOPY);
3232 x86_call_reg (s->code, X86_EAX);
3234 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
3236 if (!tree->last_instr) {
3237 tree->is_jump = TRUE;
3238 offset = 5 + s->code - s->start;
3239 x86_jump32 (s->code, s->epilog - offset);
3248 mono_llmult (gint64 a, gint64 b)
3254 mono_llmult_ovf_un (gpointer *exc, guint32 al, guint32 ah, guint32 bl, gint32 bh)
3258 // fixme: this is incredible slow
3261 goto raise_exception;
3263 res = (guint64)al * (guint64)bl;
3265 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
3267 if (t1 > 0xffffffff)
3268 goto raise_exception;
3276 *exc = mono_get_exception_overflow ();
3281 mono_lldiv (gint64 a, gint64 b)
3287 mono_llrem (gint64 a, gint64 b)
3293 mono_lldiv_un (guint64 a, guint64 b)
3299 mono_llrem_un (guint64 a, guint64 b)
3305 mono_ctree_new (MonoMemPool *mp, int op, MBTree *left, MBTree *right)
3307 MBTree *t = mono_mempool_alloc0 (mp, sizeof (MBTree));
3315 t->svt = VAL_UNKNOWN;
3321 mono_ctree_new_leaf (MonoMemPool *mp, int op)
3323 return mono_ctree_new (mp, op, NULL, NULL);
3327 arch_get_lmf_addr (void)
3331 if ((lmf = TlsGetValue (lmf_thread_id)))
3334 lmf = g_malloc (sizeof (gpointer));
3337 TlsSetValue (lmf_thread_id, lmf);
3343 mono_array_new_wrapper (MonoClass *eclass, guint32 n)
3345 MonoDomain *domain = mono_domain_get ();
3347 return mono_array_new (domain, eclass, n);
3351 mono_object_new_wrapper (MonoClass *klass)
3353 MonoDomain *domain = mono_domain_get ();
3355 return mono_object_new (domain, klass);
3359 mono_string_new_wrapper (const char *text)
3361 MonoDomain *domain = mono_domain_get ();
3363 return mono_string_new (domain, text);
3367 mono_ldstr_wrapper (MonoImage *image, guint32 index)
3369 MonoDomain *domain = mono_domain_get ();
3371 return mono_ldstr (domain, image, index);
3375 mono_ldsflda (MonoClass *klass, int offset)
3377 MonoDomain *domain = mono_domain_get ();
3381 vt = mono_class_vtable (domain, klass);
3382 addr = (char*)(vt->data) + offset;
3389 MEMCOPY (void *dest, const void *src, size_t n)
3393 printf ("MEMCPY(%p to %p [%d]) ", src, dest, n);
3395 for (i = 0; i < l; i++)
3396 printf ("%02x ", *((guint8 *)src + i));
3399 return memcpy (dest, src, n);