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>
30 #define MBTREE_TYPE MBTree
31 #define MBCGEN_TYPE MonoFlowGraph
32 #define MBCOST_DATA MonoFlowGraph
33 #define MBALLOC_STATE mono_mempool_alloc (data->mp, sizeof (MBState))
36 AMImmediate = 0, // ptr
38 AMIndex = 2, // V[REG*X]
39 AMBaseIndex = 3, // V[REG*X][REG]
52 unsigned last_instr:1;
81 gint64 mono_llmult (gint64 a, gint64 b);
82 guint64 mono_llmult_ovf (gpointer *exc, guint32 al, gint32 ah, guint32 bl, gint32 bh);
83 guint64 mono_llmult_ovf_un (gpointer *exc, guint32 al, guint32 ah, guint32 bl, guint32 bh);
84 gint64 mono_lldiv (gint64 a, gint64 b);
85 gint64 mono_llrem (gint64 a, gint64 b);
86 guint64 mono_lldiv_un (guint64 a, guint64 b);
87 guint64 mono_llrem_un (guint64 a, guint64 b);
88 gpointer mono_ldsflda (MonoClass *klass, int offset);
90 gpointer arch_get_lmf_addr (void);
93 mono_array_new_wrapper (MonoClass *eclass, guint32 n);
95 mono_object_new_wrapper (MonoClass *klass);
97 mono_string_new_wrapper (const char *text);
99 mono_ldstr_wrapper (MonoImage *image, guint32 index);
102 get_mono_object_isinst (void);
104 #define MB_OPT_LEVEL 1
106 #if MB_OPT_LEVEL == 0
107 #define MB_USE_OPT1(c) 65535
108 #define MB_USE_OPT2(c) 65535
110 #if MB_OPT_LEVEL == 1
111 #define MB_USE_OPT1(c) c
112 #define MB_USE_OPT2(c) 65535
114 #if MB_OPT_LEVEL >= 2
115 #define MB_USE_OPT1(c) c
116 #define MB_USE_OPT2(c) c
121 #define REAL_PRINT_REG(text,reg) \
122 mono_assert (reg >= 0); \
123 x86_push_reg (s->code, X86_EAX); \
124 x86_push_reg (s->code, X86_EDX); \
125 x86_push_reg (s->code, X86_ECX); \
126 x86_push_reg (s->code, reg); \
127 x86_push_imm (s->code, reg); \
128 x86_push_imm (s->code, text " %d %p\n"); \
129 x86_mov_reg_imm (s->code, X86_EAX, printf); \
130 x86_call_reg (s->code, X86_EAX); \
131 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 3*4); \
132 x86_pop_reg (s->code, X86_ECX); \
133 x86_pop_reg (s->code, X86_EDX); \
134 x86_pop_reg (s->code, X86_EAX);
137 #define MEMCOPY debug_memcpy
138 void *MEMCOPY (void *dest, const void *src, size_t n);
140 #define PRINT_REG(text,reg) REAL_PRINT_REG(text,reg)
143 #define MEMCOPY memcpy
145 #define PRINT_REG(x,y)
149 /* The call instruction for virtual functions must have a known
150 * size (used by x86_magic_trampoline)
152 #define x86_call_virtual(inst,basereg,disp) \
154 *(inst)++ = (unsigned char)0xff; \
155 x86_address_byte ((inst), 2, 2, (basereg)); \
156 x86_imm_emit32 ((inst), (disp)); \
159 /* emit an exception if condition is fail */
160 #define EMIT_COND_SYSTEM_EXCEPTION(cond,signed,exc_name) \
163 x86_branch8 (s->code, cond, 10, signed); \
164 x86_push_imm (s->code, exc_name); \
165 t = arch_get_throw_exception_by_name (); \
166 mono_add_jump_info (s, s->code + 1, \
167 MONO_JUMP_INFO_ABS, t); \
168 x86_call_code (s->code, 0); \
174 # terminal definitions
178 %term CONST_I4 CONST_I8 CONST_R4 CONST_R8
179 %term LDIND_I1 LDIND_U1 LDIND_I2 LDIND_U2 LDIND_I4 LDIND_REF LDIND_I8 LDIND_R4 LDIND_R8
180 %term LDIND_U4 LDIND_OBJ
181 %term STIND_I1 STIND_I2 STIND_I4 STIND_REF STIND_I8 STIND_R4 STIND_R8 STIND_OBJ
182 %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
183 %term BREAK SWITCH BR RET_VOID RET RET_OBJ ENDFINALLY
184 %term ADD ADD_OVF ADD_OVF_UN SUB SUB_OVF SUB_OVF_UN MUL MUL_OVF MUL_OVF_UN
185 %term DIV DIV_UN REM REM_UN AND OR XOR SHL SHR SHR_UN NEG NOT
186 %term BLT BLT_UN BEQ BNE_UN BRTRUE BRFALSE BGE BGE_UN BLE BLE_UN BGT BGT_UN
187 %term CEQ CLT CLT_UN CGT CGT_UN
188 %term CONV_I4 CONV_I1 CONV_I2 CONV_I8 CONV_U8 CONV_R4 CONV_R8 CONV_R_UN
189 %term INTF_ADDR VFUNC_ADDR NOP NEWARR NEWOBJ NEWSTRUCT CPOBJ POP INITOBJ
190 %term ISINST CASTCLASS UNBOX
191 %term CONV_OVF_I1 CONV_OVF_U1 CONV_OVF_I2 CONV_OVF_U2 CONV_OVF_U4 CONV_OVF_U8 CONV_OVF_I4
192 %term CONV_OVF_I4_UN CONV_OVF_U1_UN CONV_OVF_U2_UN
193 %term CONV_OVF_I2_UN CONV_OVF_I8_UN CONV_OVF_I1_UN
194 %term EXCEPTION THROW RETHROW HANDLER SAVE_LMF RESTORE_LMF
195 %term LDLEN LDELEMA LDFTN TOSTRING LDSTR LDSFLDA
211 tree->data.ainfo.offset = tree->data.i;
212 tree->data.ainfo.amode = AMImmediate;
216 tree->data.ainfo.offset = tree->data.i;
217 tree->data.ainfo.amode = AMImmediate;
220 acon: ADD (ADDR_G, CONST_I4) {
221 tree->data.ainfo.offset = (unsigned)tree->left->data.p + tree->right->data.i;
222 tree->data.ainfo.amode = AMImmediate;
228 tree->data.ainfo.offset = 0;
229 tree->data.ainfo.basereg = tree->reg1;
230 tree->data.ainfo.amode = AMBase;
233 base: ADD (reg, acon) {
234 tree->data.ainfo.offset = tree->right->data.i;
235 tree->data.ainfo.basereg = tree->left->reg1;
236 tree->data.ainfo.amode = AMBase;
240 tree->data.ainfo.offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
241 tree->data.ainfo.basereg = X86_EBP;
242 tree->data.ainfo.amode = AMBase;
246 tree->data.ainfo.offset = 0;
247 tree->data.ainfo.indexreg = tree->reg1;
248 tree->data.ainfo.shift = 0;
249 tree->data.ainfo.amode = AMIndex;
252 index: SHL (reg, CONST_I4) {
253 tree->data.ainfo.offset = 0;
254 tree->data.ainfo.amode = AMIndex;
255 tree->data.ainfo.indexreg = tree->left->reg1;
256 tree->data.ainfo.shift = tree->right->data.i;
258 MBCOND (tree->right->data.i == 0 ||
259 tree->right->data.i == 1 ||
260 tree->right->data.i == 2 ||
261 tree->right->data.i == 3);
266 index: MUL (reg, CONST_I4) {
267 static int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
269 tree->data.ainfo.offset = 0;
270 tree->data.ainfo.amode = AMIndex;
271 tree->data.ainfo.indexreg = tree->left->reg1;
272 tree->data.ainfo.shift = fast_log2 [tree->right->data.i];
274 MBCOND (tree->right->data.i == 1 ||
275 tree->right->data.i == 2 ||
276 tree->right->data.i == 4 ||
277 tree->right->data.i == 8);
286 addr: ADD (index, base) {
287 tree->data.ainfo.offset = tree->right->data.ainfo.offset;
288 tree->data.ainfo.basereg = tree->right->data.ainfo.basereg;
289 tree->data.ainfo.amode = tree->left->data.ainfo.amode |
290 tree->right->data.ainfo.amode;
291 tree->data.ainfo.shift = tree->left->data.ainfo.shift;
292 tree->data.ainfo.indexreg = tree->left->data.ainfo.indexreg;
295 # we pass exception in ECX to catch handler
297 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
299 if (tree->reg1 != X86_ECX)
300 x86_mov_reg_reg (s->code, tree->reg1, X86_ECX, 4);
302 /* store it so that we can RETHROW it later */
303 x86_mov_membase_reg (s->code, X86_EBP, offset, tree->reg1, 4);
309 x86_push_reg (s->code, tree->left->reg1);
310 target = arch_get_throw_exception ();
311 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, target);
312 x86_call_code (s->code, target);
316 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
319 x86_push_membase (s->code, X86_EBP, offset);
320 target = arch_get_throw_exception ();
321 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, target);
322 x86_call_code (s->code, target);
326 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_BB, tree->data.bb);
327 x86_call_imm (s->code, 0);
335 /* save all caller saved regs */
336 x86_push_reg (s->code, X86_EBX);
337 x86_push_reg (s->code, X86_EDI);
338 x86_push_reg (s->code, X86_ESI);
339 x86_push_reg (s->code, X86_EBP);
342 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_IP, NULL);
343 x86_push_imm (s->code, s->code);
345 /* save method info */
346 x86_push_imm (s->code, tree->data.m);
347 /* get the address of lmf for the current thread */
348 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, arch_get_lmf_addr);
349 x86_call_code (s->code, arch_get_lmf_addr);
351 x86_push_reg (s->code, X86_EAX);
352 /* push *lfm (previous_lmf) */
353 x86_push_membase (s->code, X86_EAX, 0);
355 x86_mov_membase_reg (s->code, X86_EAX, 0, X86_ESP, 4);
359 /* ebx = previous_lmf */
360 x86_pop_reg (s->code, X86_EBX);
362 x86_pop_reg (s->code, X86_EDI);
363 /* *(lmf) = previous_lmf */
364 x86_mov_membase_reg (s->code, X86_EDI, 0, X86_EBX, 4);
366 /* discard method info */
367 x86_pop_reg (s->code, X86_ESI);
369 /* discard save IP */
370 x86_pop_reg (s->code, X86_ESI);
372 /* restore caller saved regs */
373 x86_pop_reg (s->code, X86_EBP);
374 x86_pop_reg (s->code, X86_ESI);
375 x86_pop_reg (s->code, X86_EDI);
376 x86_pop_reg (s->code, X86_EBX);
379 stmt: STIND_I4 (addr, reg) {
380 PRINT_REG ("STIND_I4", tree->right->reg1);
382 switch (tree->left->data.ainfo.amode) {
385 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
389 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
390 tree->left->data.ainfo.offset, tree->right->reg1, 4);
393 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
394 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
395 tree->right->reg1, 4);
398 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
399 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
400 tree->right->reg1, 4);
405 stmt: STIND_REF (addr, reg) {
406 PRINT_REG ("STIND_REF", tree->right->reg1);
408 switch (tree->left->data.ainfo.amode) {
411 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
415 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
416 tree->left->data.ainfo.offset, tree->right->reg1, 4);
419 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
420 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
421 tree->right->reg1, 4);
424 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
425 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
426 tree->right->reg1, 4);
431 stmt: STIND_I1 (addr, reg) {
432 PRINT_REG ("STIND_I1", tree->right->reg1);
434 switch (tree->left->data.ainfo.amode) {
437 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 1);
441 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
442 tree->left->data.ainfo.offset, tree->right->reg1, 1);
445 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
446 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
447 tree->right->reg1, 1);
450 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
451 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
452 tree->right->reg1, 1);
457 stmt: STIND_I2 (addr, reg) {
458 PRINT_REG ("STIND_I2", tree->right->reg1);
460 switch (tree->left->data.ainfo.amode) {
463 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 2);
467 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
468 tree->left->data.ainfo.offset, tree->right->reg1, 2);
471 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
472 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
473 tree->right->reg1, 2);
476 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
477 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
478 tree->right->reg1, 2);
483 reg: LDIND_I4 (addr) {
485 switch (tree->left->data.ainfo.amode) {
488 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
492 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
493 tree->left->data.ainfo.offset, 4);
496 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
497 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
500 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
501 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
502 tree->left->data.ainfo.shift, 4);
507 PRINT_REG ("LDIND_I4", tree->reg1);
510 reg: LDIND_REF (addr) {
512 switch (tree->left->data.ainfo.amode) {
515 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
519 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
520 tree->left->data.ainfo.offset, 4);
523 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
524 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
527 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
528 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
529 tree->left->data.ainfo.shift, 4);
534 PRINT_REG ("LDIND_REF", tree->reg1);
537 reg: LDIND_I1 (addr) {
538 switch (tree->left->data.ainfo.amode) {
541 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, FALSE);
545 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
546 tree->left->data.ainfo.offset, TRUE, FALSE);
549 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
550 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, TRUE, FALSE);
553 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
554 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
555 tree->left->data.ainfo.shift, TRUE, FALSE);
559 PRINT_REG ("LDIND_I1", tree->reg1);
562 reg: LDIND_U1 (addr) {
563 switch (tree->left->data.ainfo.amode) {
566 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, FALSE);
570 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
571 tree->left->data.ainfo.offset, FALSE, FALSE);
574 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
575 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, FALSE, FALSE);
578 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
579 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
580 tree->left->data.ainfo.shift, FALSE, FALSE);
584 PRINT_REG ("LDIND_U1", tree->reg1);
587 reg: LDIND_I2 (addr) {
588 switch (tree->left->data.ainfo.amode) {
591 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, TRUE);
595 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
596 tree->left->data.ainfo.offset, TRUE, TRUE);
599 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
600 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, TRUE, TRUE);
603 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
604 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
605 tree->left->data.ainfo.shift, TRUE, TRUE);
609 PRINT_REG ("LDIND_U2", tree->reg1);
612 reg: LDIND_U2 (addr) {
613 switch (tree->left->data.ainfo.amode) {
616 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, TRUE);
620 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
621 tree->left->data.ainfo.offset, FALSE, TRUE);
624 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
625 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, FALSE, TRUE);
628 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
629 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
630 tree->left->data.ainfo.shift, FALSE, TRUE);
634 PRINT_REG ("LDIND_U2", tree->reg1);
637 reg: LDIND_U4 (addr) {
638 switch (tree->left->data.ainfo.amode) {
641 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
645 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
646 tree->left->data.ainfo.offset, 4);
649 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
650 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
653 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
654 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
655 tree->left->data.ainfo.shift, 4);
659 PRINT_REG ("LDIND_U4", tree->reg1);
663 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
664 x86_lea_membase (s->code, tree->reg1, X86_EBP, offset);
666 PRINT_REG ("ADDR_L", tree->reg1);
671 x86_mov_reg_imm (s->code, tree->reg1, tree->data.p);
675 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
679 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
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 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
717 reg: CONV_OVF_I1_UN (reg) {
718 /* probe values between 0 to 128 */
719 x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff80);
720 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
721 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
724 reg: CONV_OVF_U1 (reg) {
725 /* Keep in sync with CONV_OVF_U1_UN routine below, they are the same on 32-bit machines */
726 /* probe value to be within 0 to 255 */
727 x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff00);
728 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
729 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
732 reg: CONV_OVF_U1_UN (reg) {
733 /* Keep in sync with CONV_OVF_U1 routine above, they are the same on 32-bit machines */
734 /* probe value to be within 0 to 255 */
735 x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff00);
736 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
737 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
740 reg: CONV_OVF_I2 (reg) {
741 /* Probe value to be within -32768 and 32767 */
742 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 32767);
743 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, TRUE, "OverflowException");
744 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, -32768);
745 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GE, TRUE, "OverflowException");
746 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
749 reg: CONV_OVF_U2 (reg) {
750 /* Keep in sync with CONV_OVF_U2_UN below, they are the same on 32-bit machines */
751 /* Probe value to be within 0 and 65535 */
752 x86_test_reg_imm (s->code, tree->left->reg1, 0xffff0000);
753 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
754 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
757 reg: CONV_OVF_U2_UN (reg) {
758 /* Keep in sync with CONV_OVF_U2 above, they are the same on 32-bit machines */
759 /* Probe value to be within 0 and 65535 */
760 x86_test_reg_imm (s->code, tree->left->reg1, 0xffff0000);
761 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
762 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
765 reg: CONV_OVF_I2_UN (reg) {
766 /* Convert uint value into short, value within 0 and 32767 */
767 x86_test_reg_imm (s->code, tree->left->reg1, 0xffff8000);
768 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
769 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
772 reg: MUL (reg, reg) {
773 x86_imul_reg_reg (s->code, tree->left->reg1, tree->right->reg1);
775 if (tree->reg1 != tree->left->reg1)
776 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
779 reg: MUL_OVF (reg, reg) {
780 x86_imul_reg_reg (s->code, tree->left->reg1, tree->right->reg1);
781 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
783 if (tree->reg1 != tree->left->reg1)
784 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
787 reg: MUL_OVF_UN (reg, reg) {
788 mono_assert (tree->right->reg1 != X86_EAX);
790 if (tree->left->reg1 != X86_EAX)
791 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
793 x86_mul_reg (s->code, tree->right->reg1, FALSE);
794 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
796 mono_assert (tree->reg1 == X86_EAX &&
797 tree->reg2 == X86_EDX);
800 reg: DIV (reg, reg) {
801 mono_assert (tree->right->reg1 != X86_EAX);
803 if (tree->left->reg1 != X86_EAX)
804 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
807 x86_div_reg (s->code, tree->right->reg1, TRUE);
809 mono_assert (tree->reg1 == X86_EAX &&
810 tree->reg2 == X86_EDX);
813 reg: DIV_UN (reg, reg) {
814 mono_assert (tree->right->reg1 != X86_EAX);
816 if (tree->left->reg1 != X86_EAX)
817 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
820 x86_div_reg (s->code, tree->right->reg1, FALSE);
822 mono_assert (tree->reg1 == X86_EAX &&
823 tree->reg2 == X86_EDX);
826 reg: REM (reg, reg) {
827 mono_assert (tree->right->reg1 != X86_EAX);
828 mono_assert (tree->right->reg1 != X86_EDX);
830 if (tree->left->reg1 != X86_EAX)
831 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
833 /* sign extend to 64bit in EAX/EDX */
835 x86_div_reg (s->code, tree->right->reg1, TRUE);
836 x86_mov_reg_reg (s->code, X86_EAX, X86_EDX, 4);
838 mono_assert (tree->reg1 == X86_EAX &&
839 tree->reg2 == X86_EDX);
842 reg: REM_UN (reg, reg) {
843 mono_assert (tree->right->reg1 != X86_EAX);
844 mono_assert (tree->right->reg1 != X86_EDX);
846 if (tree->left->reg1 != X86_EAX)
847 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
849 /* zero extend to 64bit in EAX/EDX */
850 x86_mov_reg_imm (s->code, X86_EDX, 0);
851 x86_div_reg (s->code, tree->right->reg1, FALSE);
852 x86_mov_reg_reg (s->code, X86_EAX, X86_EDX, 4);
854 mono_assert (tree->reg1 == X86_EAX &&
855 tree->reg2 == X86_EDX);
858 reg: ADD (reg, CONST_I4) "MB_USE_OPT1(0)" {
859 if (tree->right->data.i == 1)
860 x86_inc_reg (s->code, tree->left->reg1);
862 x86_alu_reg_imm (s->code, X86_ADD, tree->left->reg1, tree->right->data.i);
864 if (tree->reg1 != tree->left->reg1)
865 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
869 reg: ADD (reg, reg) {
870 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
872 if (tree->reg1 != tree->left->reg1)
873 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
876 reg: ADD_OVF (reg, reg) {
877 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
878 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
880 if (tree->reg1 != tree->left->reg1)
881 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
884 reg: ADD_OVF_UN (reg, reg) {
885 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
886 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
888 if (tree->reg1 != tree->left->reg1)
889 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
892 reg: SUB (reg, CONST_I4) "MB_USE_OPT1(0)" {
893 if (tree->right->data.i == 1)
894 x86_dec_reg (s->code, tree->left->reg1);
896 x86_alu_reg_imm (s->code, X86_SUB, tree->left->reg1, tree->right->data.i);
898 if (tree->reg1 != tree->left->reg1)
899 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
902 reg: SUB (reg, reg) {
903 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
905 if (tree->reg1 != tree->left->reg1)
906 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
909 reg: SUB_OVF (reg, reg) {
910 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
911 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
913 if (tree->reg1 != tree->left->reg1)
914 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
917 reg: SUB_OVF_UN (reg, reg) {
918 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
919 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
921 if (tree->reg1 != tree->left->reg1)
922 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
925 reg: CEQ (reg, reg) {
926 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
927 x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
928 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
931 reg: CGT (reg, reg) {
932 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
933 x86_set_reg (s->code, X86_CC_GT, tree->reg1, TRUE);
934 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
937 reg: CGT_UN (reg, reg) {
938 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
939 x86_set_reg (s->code, X86_CC_GT, tree->reg1, FALSE);
940 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
943 reg: CLT (reg, reg) {
944 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
945 x86_set_reg (s->code, X86_CC_LT, tree->reg1, TRUE);
946 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
949 reg: CLT_UN (reg, reg) {
950 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
951 x86_set_reg (s->code, X86_CC_LT, tree->reg1, FALSE);
952 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
955 reg: AND (reg, reg) {
956 x86_alu_reg_reg (s->code, X86_AND, tree->left->reg1, tree->right->reg1);
958 if (tree->reg1 != tree->left->reg1)
959 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
963 x86_alu_reg_reg (s->code, X86_OR, tree->left->reg1, tree->right->reg1);
965 if (tree->reg1 != tree->left->reg1)
966 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
969 reg: XOR (reg, reg) {
970 x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->right->reg1);
972 if (tree->reg1 != tree->left->reg1)
973 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
977 x86_neg_reg (s->code, tree->left->reg1);
979 if (tree->reg1 != tree->left->reg1)
980 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
984 x86_not_reg (s->code, tree->left->reg1);
986 if (tree->reg1 != tree->left->reg1)
987 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
990 reg: SHL (reg, CONST_I4) {
991 x86_shift_reg_imm (s->code, X86_SHL, tree->left->reg1, tree->right->data.i);
993 if (tree->reg1 != tree->left->reg1)
994 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
997 reg: SHL (reg, reg) {
998 if (tree->right->reg1 != X86_ECX)
999 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1000 x86_shift_reg (s->code, X86_SHL, tree->left->reg1);
1002 if (tree->reg1 != tree->left->reg1)
1003 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1005 mono_assert (tree->reg1 != X86_ECX &&
1006 tree->left->reg1 != X86_ECX);
1009 reg: SHR (reg, CONST_I4) {
1010 x86_shift_reg_imm (s->code, X86_SAR, tree->left->reg1, tree->right->data.i);
1012 if (tree->reg1 != tree->left->reg1)
1013 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1016 reg: SHR (reg, reg) {
1017 if (tree->right->reg1 != X86_ECX)
1018 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1019 x86_shift_reg (s->code, X86_SAR, tree->left->reg1);
1021 if (tree->reg1 != tree->left->reg1)
1022 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1024 mono_assert (tree->reg1 != X86_ECX &&
1025 tree->left->reg1 != X86_ECX);
1028 reg: SHR_UN (reg, CONST_I4) {
1029 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg1, tree->right->data.i);
1031 if (tree->reg1 != tree->left->reg1)
1032 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1035 reg: SHR_UN (reg, reg) {
1036 if (tree->right->reg1 != X86_ECX)
1037 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1038 x86_shift_reg (s->code, X86_SHR, tree->left->reg1);
1040 if (tree->reg1 != tree->left->reg1)
1041 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1043 mono_assert (tree->reg1 != X86_ECX &&
1044 tree->left->reg1 != X86_ECX);
1047 reg: LDSFLDA (CONST_I4) {
1048 if (tree->reg1 != X86_EAX)
1049 x86_push_reg (s->code, X86_EAX);
1050 x86_push_reg (s->code, X86_ECX);
1051 x86_push_reg (s->code, X86_EDX);
1053 x86_push_imm (s->code, tree->left->data.i);
1054 x86_push_imm (s->code, tree->data.klass);
1055 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_ldsflda);
1056 x86_call_code (s->code, 0);
1057 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1059 x86_pop_reg (s->code, X86_EDX);
1060 x86_pop_reg (s->code, X86_ECX);
1061 if (tree->reg1 != X86_EAX) {
1062 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1063 x86_pop_reg (s->code, X86_EAX);
1069 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
1070 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NE, TRUE, "NullReferenceException");
1072 x86_mov_reg_membase (s->code, tree->reg1, tree->left->reg1,
1073 G_STRUCT_OFFSET (MonoArray, bounds), 4);
1074 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1,
1075 G_STRUCT_OFFSET (MonoArrayBounds, length), 4);
1078 reg: LDELEMA (reg, reg) {
1079 x86_alu_reg_membase (s->code, X86_CMP, tree->right->reg1, tree->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length));
1080 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LT, FALSE, "IndexOutOfRangeException");
1082 if (tree->data.i == 1 || tree->data.i == 2 ||
1083 tree->data.i == 4 || tree->data.i == 8) {
1084 static int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
1085 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1,
1086 G_STRUCT_OFFSET (MonoArray, vector), tree->right->reg1,
1087 fast_log2 [tree->data.i]);
1089 x86_imul_reg_reg_imm (s->code, tree->right->reg1, tree->right->reg1, tree->data.i);
1090 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
1091 x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, G_STRUCT_OFFSET (MonoArray, vector));
1096 if (tree->reg1 != X86_EAX)
1097 x86_push_reg (s->code, X86_EAX);
1098 x86_push_reg (s->code, X86_ECX);
1099 x86_push_reg (s->code, X86_EDX);
1101 x86_push_imm (s->code, tree->data.p);
1102 x86_push_imm (s->code, s->method->klass->image);
1103 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_ldstr_wrapper);
1104 x86_call_code (s->code, 0);
1105 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1107 x86_pop_reg (s->code, X86_EDX);
1108 x86_pop_reg (s->code, X86_ECX);
1109 if (tree->reg1 != X86_EAX) {
1110 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1111 x86_pop_reg (s->code, X86_EAX);
1114 PRINT_REG ("LDSTR", tree->reg1);
1117 reg: TOSTRING (reg) {
1118 guint8 *start = s->code, *l1, *le;
1123 for (i = 0; i < 2; i++) {
1126 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
1127 x86_branch8 (s->code, X86_CC_EQ, le - l1, FALSE);
1130 if (tree->reg1 != X86_EAX)
1131 x86_push_reg (s->code, X86_EAX);
1132 x86_push_reg (s->code, X86_ECX);
1133 x86_push_reg (s->code, X86_EDX);
1135 x86_push_reg (s->code, tree->left->reg1);
1136 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_string_new_wrapper);
1137 x86_call_code (s->code, 0);
1138 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
1140 x86_pop_reg (s->code, X86_EDX);
1141 x86_pop_reg (s->code, X86_ECX);
1142 if (tree->reg1 != X86_EAX) {
1143 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1144 x86_pop_reg (s->code, X86_EAX);
1152 if (tree->reg1 != X86_EAX)
1153 x86_push_reg (s->code, X86_EAX);
1154 x86_push_reg (s->code, X86_ECX);
1155 x86_push_reg (s->code, X86_EDX);
1157 x86_push_reg (s->code, tree->left->reg1);
1158 x86_push_imm (s->code, tree->data.p);
1159 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_array_new_wrapper);
1160 x86_call_code (s->code, 0);
1161 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer) + 4);
1163 x86_pop_reg (s->code, X86_EDX);
1164 x86_pop_reg (s->code, X86_ECX);
1165 if (tree->reg1 != X86_EAX) {
1166 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1167 x86_pop_reg (s->code, X86_EAX);
1170 PRINT_REG ("NEWARR", tree->reg1);
1174 if (tree->reg1 != X86_EAX)
1175 x86_push_reg (s->code, X86_EAX);
1176 x86_push_reg (s->code, X86_ECX);
1177 x86_push_reg (s->code, X86_EDX);
1179 x86_push_imm (s->code, tree->data.klass);
1180 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_object_new_wrapper);
1181 x86_call_code (s->code, 0);
1182 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
1184 x86_pop_reg (s->code, X86_EDX);
1185 x86_pop_reg (s->code, X86_ECX);
1186 if (tree->reg1 != X86_EAX) {
1187 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1188 x86_pop_reg (s->code, X86_EAX);
1190 PRINT_REG ("NEWOBJ", tree->reg1);
1194 int size = tree->data.i;
1197 mono_assert (size > 0);
1202 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);
1203 x86_mov_reg_reg (s->code, tree->reg1, X86_ESP, 4);
1207 if (tree->reg1 != tree->left->reg1)
1208 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1210 x86_test_reg_reg (s->code, tree->reg1, tree->reg1);
1211 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NE, TRUE, "NullReferenceException");
1213 x86_push_reg (s->code, tree->reg1);
1214 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, 0, 4);
1215 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, 0, 4);
1216 x86_alu_membase_imm (s->code, X86_CMP, tree->reg1,
1217 G_STRUCT_OFFSET (MonoClass, element_class), ((int)(tree->data.klass->element_class)));
1218 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "InvalidCastException");
1219 x86_pop_reg (s->code, tree->reg1);
1220 x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, sizeof (MonoObject));
1223 reg: CASTCLASS (reg) {
1224 guint8 *start = s->code, *l1, *l2, *le;
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_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
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 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_object_isinst);
1244 x86_call_code (s->code, 0);
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 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_object_isinst);
1271 x86_call_code (s->code, 0);
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 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_BB, tree->data.bb);
1349 x86_jump32 (s->code, 0);
1352 stmt: BLT (reg, reg) 1 {
1353 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1354 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1355 x86_branch32 (s->code, X86_CC_LT, 0, TRUE);
1358 stmt: BLT (reg, CONST_I4) "MB_USE_OPT1(0)" {
1359 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1360 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1361 x86_branch32 (s->code, X86_CC_LT, 0, TRUE);
1364 stmt: BLT_UN (reg, reg) 1 {
1365 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1366 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1367 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
1370 stmt: BLT_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1371 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1372 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1373 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
1376 stmt: BGT (reg, reg) 1 {
1377 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1378 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1379 x86_branch32 (s->code, X86_CC_GT, 0, TRUE);
1382 stmt: BGT (reg, CONST_I4) "MB_USE_OPT1(0)" {
1383 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1384 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1385 x86_branch32 (s->code, X86_CC_GT, 0, TRUE);
1388 stmt: BGT_UN (reg, reg) 1 {
1389 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1390 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1391 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
1394 stmt: BGT_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1395 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1396 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1397 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
1400 stmt: BEQ (reg, CONST_I4) "MB_USE_OPT1(0)" {
1401 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1402 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1403 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
1406 stmt: BEQ (reg, reg) 1 {
1407 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1408 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1409 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
1412 stmt: BNE_UN (reg, reg) 1 {
1413 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1414 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1415 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
1418 stmt: BNE_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1419 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1420 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1421 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
1424 stmt: BGE (reg, reg) 1 {
1425 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1426 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1427 x86_branch32 (s->code, X86_CC_GE, 0, TRUE);
1430 stmt: BGE (reg, CONST_I4) "MB_USE_OPT1(0)" {
1431 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1432 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1433 x86_branch32 (s->code, X86_CC_GE, 0, TRUE);
1436 stmt: BGE_UN (reg, reg) 1 {
1437 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1438 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1439 x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
1442 stmt: BGE_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1443 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1444 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1445 x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
1448 stmt: BLE (reg, reg) 1 {
1449 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1450 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1451 x86_branch32 (s->code, X86_CC_LE, 0, TRUE);
1454 stmt: BLE (reg, CONST_I4) "MB_USE_OPT1(0)" {
1455 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1456 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1457 x86_branch32 (s->code, X86_CC_LE, 0, TRUE);
1460 stmt: BLE_UN (reg, reg) 1 {
1461 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
1462 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1463 x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
1466 stmt: BLE_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
1467 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
1468 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1469 x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
1472 stmt: BRTRUE (reg) {
1473 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
1474 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1475 x86_branch32 (s->code, X86_CC_NE, 0, TRUE);
1478 stmt: BRFALSE (reg) {
1479 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
1480 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
1481 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
1485 x86_breakpoint (s->code);
1489 if (tree->left->reg1 != X86_EAX)
1490 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1492 if (!tree->last_instr) {
1493 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_EPILOG, NULL);
1494 x86_jump32 (s->code, 0);
1499 if (!tree->last_instr) {
1500 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_EPILOG, NULL);
1501 x86_jump32 (s->code, 0);
1506 stmt: ARG_I4 (LDIND_I4 (addr)) {
1507 MBTree *at = tree->left->left;
1509 switch (at->data.ainfo.amode) {
1512 x86_push_mem (s->code, at->data.ainfo.offset);
1516 x86_push_membase (s->code, at->data.ainfo.basereg, at->data.ainfo.offset);
1519 x86_push_memindex (s->code, X86_NOBASEREG, at->data.ainfo.offset,
1520 at->data.ainfo.indexreg, at->data.ainfo.shift);
1523 x86_push_memindex (s->code, at->data.ainfo.basereg,
1524 at->data.ainfo.offset, at->data.ainfo.indexreg,
1525 at->data.ainfo.shift);
1530 stmt: ARG_I4 (LDIND_U4 (addr)) {
1531 MBTree *at = tree->left->left;
1533 switch (at->data.ainfo.amode) {
1536 x86_push_mem (s->code, at->data.ainfo.offset);
1540 x86_push_membase (s->code, at->data.ainfo.basereg, at->data.ainfo.offset);
1543 x86_push_memindex (s->code, X86_NOBASEREG, at->data.ainfo.offset,
1544 at->data.ainfo.indexreg, at->data.ainfo.shift);
1547 x86_push_memindex (s->code, at->data.ainfo.basereg,
1548 at->data.ainfo.offset, at->data.ainfo.indexreg,
1549 at->data.ainfo.shift);
1554 stmt: ARG_I4 (reg) {
1555 x86_push_reg (s->code, tree->left->reg1);
1556 PRINT_REG ("ARG_I4", tree->left->reg1);
1559 # fixme: we must free the allocated strings somewhere
1560 stmt: ARG_STRING (reg) {
1561 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
1562 x86_push_reg (s->code, X86_EAX);
1563 x86_push_reg (s->code, X86_ECX);
1564 x86_push_reg (s->code, X86_EDX);
1566 x86_push_reg (s->code, tree->left->reg1);
1567 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_string_to_utf8);
1568 x86_call_code (s->code, 0);
1569 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
1571 x86_mov_membase_reg (s->code, X86_ESP, 12, X86_EAX, 4);
1573 x86_pop_reg (s->code, X86_EDX);
1574 x86_pop_reg (s->code, X86_ECX);
1575 x86_pop_reg (s->code, X86_EAX);
1578 stmt: ARG_I4 (ADDR_G) {
1579 x86_push_imm (s->code, tree->left->data.p);
1582 stmt: ARG_I4 (CONST_I4) "MB_USE_OPT1(0)" {
1583 x86_push_imm (s->code, tree->left->data.i);
1587 PRINT_REG ("THIS", tree->reg1);
1592 reg: CALL_I4 (this, reg) {
1593 MethodCallInfo *ci = tree->data.ci;
1595 int lreg = tree->left->reg1;
1596 int rreg = tree->right->reg1;
1598 if (lreg == treg || rreg == treg)
1600 if (lreg == treg || rreg == treg)
1602 if (lreg == treg || rreg == treg)
1603 mono_assert_not_reached ();
1605 if (tree->left->op != MB_TERM_NOP) {
1606 mono_assert (lreg >= 0);
1607 x86_push_reg (s->code, lreg);
1610 if (ci->vtype_num) {
1611 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1612 x86_lea_membase (s->code, treg, X86_EBP, offset);
1613 x86_push_reg (s->code, treg);
1616 x86_call_reg (s->code, rreg);
1619 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1621 PRINT_REG ("CALL_I4", tree->reg1);
1623 mono_assert (tree->reg1 == X86_EAX);
1626 reg: CALL_I4 (this, ADDR_G) {
1627 MethodCallInfo *ci = tree->data.ci;
1628 int lreg = tree->left->reg1;
1634 if (tree->left->op != MB_TERM_NOP) {
1635 mono_assert (lreg >= 0);
1636 x86_push_reg (s->code, lreg);
1639 if (ci->vtype_num) {
1640 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1641 x86_lea_membase (s->code, treg, X86_EBP, offset);
1642 x86_push_reg (s->code, treg);
1645 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, tree->right->data.p);
1646 x86_call_code (s->code, 0);
1649 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1651 PRINT_REG ("CALL_I4", tree->reg1);
1653 mono_assert (tree->reg1 == X86_EAX);
1656 reg: LDFTN (reg, INTF_ADDR) {
1657 int lreg = tree->left->reg1;
1659 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1660 x86_mov_reg_membase (s->code, lreg, lreg,
1661 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
1662 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
1663 x86_mov_reg_membase (s->code, tree->reg1, lreg, tree->right->data.m->slot << 2, 4);
1666 reg: CALL_I4 (this, INTF_ADDR) {
1667 MethodCallInfo *ci = tree->data.ci;
1668 int lreg = tree->left->reg1;
1674 if (tree->left->op != MB_TERM_NOP) {
1675 mono_assert (lreg >= 0);
1676 x86_push_reg (s->code, lreg);
1679 if (ci->vtype_num) {
1680 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1681 x86_lea_membase (s->code, treg, X86_EBP, offset);
1682 x86_push_reg (s->code, treg);
1685 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1686 x86_mov_reg_membase (s->code, lreg, lreg,
1687 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
1688 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
1689 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
1692 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1694 PRINT_REG ("CALL_I4(INTERFACE)", tree->reg1);
1696 mono_assert (tree->reg1 == X86_EAX);
1699 reg: LDFTN (reg, VFUNC_ADDR) {
1700 int lreg = tree->left->reg1;
1702 x86_mov_reg_membase (s->code, tree->reg1, lreg, 0, 4);
1704 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2), 4);
1707 reg: CALL_I4 (this, VFUNC_ADDR) {
1708 MethodCallInfo *ci = tree->data.ci;
1709 int lreg = tree->left->reg1;
1715 if (tree->left->op != MB_TERM_NOP) {
1716 mono_assert (lreg >= 0);
1717 x86_push_reg (s->code, lreg);
1720 if (ci->vtype_num) {
1721 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1722 x86_lea_membase (s->code, treg, X86_EBP, offset);
1723 x86_push_reg (s->code, treg);
1726 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1727 x86_call_virtual (s->code, lreg,
1728 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
1731 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1733 PRINT_REG ("CALL_I4(VIRTUAL)", tree->reg1);
1735 mono_assert (tree->reg1 == X86_EAX);
1738 stmt: CALL_VOID (this, ADDR_G) {
1739 MethodCallInfo *ci = tree->data.ci;
1740 int lreg = tree->left->reg1;
1746 if (tree->left->op != MB_TERM_NOP) {
1747 mono_assert (lreg >= 0);
1748 x86_push_reg (s->code, lreg);
1751 if (ci->vtype_num) {
1752 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1753 x86_lea_membase (s->code, treg, X86_EBP, offset);
1754 x86_push_reg (s->code, treg);
1757 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, tree->right->data.p);
1758 x86_call_code (s->code, 0);
1761 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1764 stmt: CALL_VOID (this, INTF_ADDR) {
1765 MethodCallInfo *ci = tree->data.ci;
1766 int lreg = tree->left->reg1;
1772 if (tree->left->op != MB_TERM_NOP) {
1773 mono_assert (lreg >= 0);
1774 x86_push_reg (s->code, lreg);
1777 if (ci->vtype_num) {
1778 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1779 x86_lea_membase (s->code, treg, X86_EBP, offset);
1780 x86_push_reg (s->code, treg);
1783 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1784 x86_mov_reg_membase (s->code, lreg, lreg,
1785 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
1786 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
1787 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
1790 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1793 stmt: CALL_VOID (this, VFUNC_ADDR) {
1794 MethodCallInfo *ci = tree->data.ci;
1795 int lreg = tree->left->reg1;
1801 if (tree->left->op != MB_TERM_NOP) {
1802 mono_assert (lreg >= 0);
1803 x86_push_reg (s->code, lreg);
1806 if (ci->vtype_num) {
1807 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
1808 x86_lea_membase (s->code, treg, X86_EBP, offset);
1809 x86_push_reg (s->code, treg);
1812 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1813 x86_call_virtual (s->code, lreg,
1814 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
1817 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
1820 stmt: SWITCH (reg) {
1822 guint32 *jt = (guint32 *)tree->data.p;
1824 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, jt [0]);
1825 offset = 6 + (guint32)s->code;
1826 x86_branch32 (s->code, X86_CC_GE, jt [jt [0] + 1] - offset, FALSE);
1828 x86_mov_reg_memindex (s->code, X86_EAX, X86_NOBASEREG,
1829 tree->data.i + 4, tree->left->reg1, 2, 4);
1830 x86_jump_reg (s->code, X86_EAX);
1837 reg: CONV_I1 (lreg) {
1838 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
1841 reg: CONV_I2 (lreg) {
1842 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
1845 reg: CONV_I4 (lreg) {
1846 if (tree->reg1 != tree->left->reg1)
1847 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1851 reg: CONV_OVF_I4 (lreg){
1852 guint8 *start = s->code;
1853 gpointer o1, o2, o3, o4, o5;
1857 * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000
1859 for (i = 0; i < 2; i++) {
1862 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
1864 /* If the low word top bit is set, see if we are negative */
1865 x86_branch8 (s->code, X86_CC_LT, o3 - o1, TRUE);
1868 /* We are not negative (no top bit set, check for our top word to be zero */
1869 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
1870 x86_branch8 (s->code, X86_CC_EQ, o4 - o2, TRUE);
1873 /* throw exception */
1874 x86_push_imm (s->code, "OverflowException");
1875 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS,
1876 arch_get_throw_exception_by_name ());
1877 x86_call_code (s->code, 0);
1880 /* our top bit is set, check that top word is 0xfffffff */
1881 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg2, 0xffffffff);
1884 /* nope, emit exception */
1885 x86_branch8 (s->code, X86_CC_NE, o2 - o5, TRUE);
1888 if (tree->reg1 != tree->left->reg1)
1889 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1893 reg: CONV_OVF_U4 (lreg) {
1894 /* Keep in sync with CONV_OVF_I4_UN below, they are the same on 32-bit machines */
1895 /* top word must be 0 */
1896 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
1897 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
1898 if (tree->reg1 != tree->left->reg1)
1899 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1902 reg: CONV_OVF_I4_UN (lreg) {
1903 /* Keep in sync with CONV_OVF_U4 above, they are the same on 32-bit machines */
1904 /* top word must be 0 */
1905 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
1906 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
1907 if (tree->reg1 != tree->left->reg1)
1908 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1914 x86_mov_reg_imm (s->code, tree->reg1, *((gint32 *)&tree->data.p));
1915 x86_mov_reg_imm (s->code, tree->reg2, *((gint32 *)&tree->data.p + 1));
1918 lreg: CONV_I8 (CONST_I4) {
1919 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
1921 if (tree->left->data.i >= 0)
1922 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1924 x86_mov_reg_imm (s->code, tree->reg2, -1);
1927 lreg: CONV_I8 (reg) {
1930 if (tree->reg1 != tree->left->reg1)
1931 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1933 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
1934 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1935 x86_branch8 (s->code, X86_CC_GE, 5, TRUE);
1937 x86_mov_reg_imm (s->code, tree->reg2, -1);
1938 mono_assert ((s->code - i1) == 5);
1941 lreg: CONV_U8 (CONST_I4) 1 {
1942 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
1943 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1946 lreg: CONV_OVF_U8 (CONST_I4) {
1947 if (tree->left->data.i < 0){
1948 x86_push_imm (s->code, "OverflowException");
1949 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS,
1950 arch_get_throw_exception_by_name ());
1951 x86_call_code (s->code, 0);
1953 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
1954 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1958 lreg: CONV_OVF_I8_UN (CONST_I4) {
1959 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
1960 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1963 lreg: CONV_OVF_U8 (reg) {
1964 x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
1965 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
1967 if (tree->reg1 != tree->left->reg1)
1968 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1969 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1972 lreg: CONV_OVF_I8_UN (reg) {
1973 /* Convert uint value into int64, we pass everything */
1974 if (tree->reg1 != tree->left->reg1)
1975 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1976 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
1979 stmt: STIND_I8 (addr, lreg) {
1981 switch (tree->left->data.ainfo.amode) {
1984 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
1985 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset + 4, tree->right->reg2, 4);
1989 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
1990 tree->left->data.ainfo.offset, tree->right->reg1, 4);
1991 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
1992 tree->left->data.ainfo.offset + 4, tree->right->reg2, 4);
1995 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
1996 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
1997 tree->right->reg1, 4);
1998 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset + 4,
1999 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2000 tree->right->reg2, 4);
2003 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
2004 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2005 tree->right->reg1, 4);
2006 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset + 4,
2007 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
2008 tree->right->reg2, 4);
2014 # an addr can use two address register (base and index register). The must take care
2015 # that we do not override them (thus the use of x86_lea)
2016 lreg: LDIND_I8 (addr) {
2018 switch (tree->left->data.ainfo.amode) {
2021 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
2022 x86_mov_reg_mem (s->code, tree->reg2, tree->left->data.ainfo.offset + 4, 4);
2026 x86_lea_membase (s->code, tree->reg2, tree->left->data.ainfo.basereg,
2027 tree->left->data.ainfo.offset);
2028 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
2029 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
2032 x86_lea_memindex (s->code, tree->reg2, X86_NOBASEREG, tree->left->data.ainfo.offset,
2033 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift);
2034 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
2035 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
2038 x86_lea_memindex (s->code, tree->reg2, tree->left->data.ainfo.basereg,
2039 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
2040 tree->left->data.ainfo.shift);
2041 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
2042 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
2045 PRINT_REG ("LDIND_I8_0", tree->reg1);
2046 PRINT_REG ("LDIND_I8_1", tree->reg2);
2049 lreg: SHR (lreg, CONST_I4) {
2050 if (tree->right->data.i < 32) {
2051 x86_shrd_reg_imm (s->code, tree->left->reg1, tree->left->reg2, tree->right->data.i);
2052 x86_shift_reg_imm (s->code, X86_SAR, tree->left->reg2, tree->right->data.i);
2053 if (tree->reg1 != tree->left->reg1)
2054 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2055 if (tree->reg2 != tree->left->reg2)
2056 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2057 } else if (tree->right->data.i < 64) {
2058 if (tree->reg1 != tree->left->reg2)
2059 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg2, 4);
2060 if (tree->reg2 != tree->left->reg2)
2061 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2062 x86_shift_reg_imm (s->code, X86_SAR, tree->reg2, 31);
2063 x86_shift_reg_imm (s->code, X86_SAR, tree->reg1, (tree->right->data.i - 32));
2064 } /* else unspecified result */
2067 lreg: SHR_UN (lreg, CONST_I4) {
2068 if (tree->right->data.i < 32) {
2069 x86_shrd_reg_imm (s->code, tree->left->reg1, tree->left->reg2, tree->right->data.i);
2070 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg2, tree->right->data.i);
2071 if (tree->reg1 != tree->left->reg1)
2072 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2073 if (tree->reg2 != tree->left->reg2)
2074 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2075 } else if (tree->right->data.i < 64) {
2076 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg2, 4);
2077 x86_shift_reg_imm (s->code, X86_SHR, tree->reg1, (tree->right->data.i - 32));
2078 x86_mov_reg_imm (s->code, tree->reg2, 0);
2079 } /* else unspecified result */
2082 lreg: SHR (lreg, reg) {
2083 guint8 *start = s->code;
2086 if (tree->right->reg1 != X86_ECX)
2087 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
2089 for (i = 0; i < 2; i ++) {
2091 x86_shrd_reg (s->code, tree->left->reg1, tree->left->reg2);
2092 x86_shift_reg (s->code, X86_SAR, tree->left->reg2);
2093 x86_test_reg_imm (s->code, X86_ECX, 32);
2094 o1 = 2 + s->code - s->start;
2095 x86_branch8 (s->code, X86_CC_EQ, o2 - o1, FALSE);
2096 x86_mov_reg_reg (s->code, tree->left->reg1, tree->left->reg2, 4);
2097 x86_shift_reg_imm (s->code, X86_SAR, tree->reg2, 31);
2098 o2 = s->code - s->start;
2101 if (tree->reg1 != tree->left->reg1)
2102 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2103 if (tree->reg2 != tree->left->reg2)
2104 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2107 lreg: SHR_UN (lreg, reg) {
2108 guint8 *start = s->code;
2111 if (tree->right->reg1 != X86_ECX)
2112 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
2114 for (i = 0; i < 2; i ++) {
2116 x86_shrd_reg (s->code, tree->left->reg1, tree->left->reg2);
2117 x86_shift_reg (s->code, X86_SHR, tree->left->reg2);
2118 x86_test_reg_imm (s->code, X86_ECX, 32);
2119 o1 = 2 + s->code - s->start;
2120 x86_branch8 (s->code, X86_CC_EQ, o2 - o1, FALSE);
2121 x86_mov_reg_reg (s->code, tree->left->reg1, tree->left->reg2, 4);
2122 x86_shift_reg_imm (s->code, X86_SHR, tree->reg2, 31);
2123 o2 = s->code - s->start;
2126 if (tree->reg1 != tree->left->reg1)
2127 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2128 if (tree->reg2 != tree->left->reg2)
2129 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2132 lreg: SHL (lreg, CONST_I4) {
2133 if (tree->right->data.i < 32) {
2134 x86_shld_reg_imm (s->code, tree->left->reg2, tree->left->reg1, tree->right->data.i);
2135 x86_shift_reg_imm (s->code, X86_SHL, tree->left->reg1, tree->right->data.i);
2136 if (tree->reg1 != tree->left->reg1)
2137 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2138 if (tree->reg2 != tree->left->reg2)
2139 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2140 } else if (tree->right->data.i < 64) {
2141 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg1, 4);
2142 x86_shift_reg_imm (s->code, X86_SHL, tree->reg2, (tree->right->data.i - 32));
2143 x86_alu_reg_reg (s->code, X86_XOR, tree->reg1, tree->reg1);
2144 } /* else unspecified result */
2147 lreg: SHL (lreg, reg) {
2148 guint8 *start = s->code;
2151 if (tree->right->reg1 != X86_ECX)
2152 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
2154 for (i = 0; i < 2; i ++) {
2156 x86_shld_reg (s->code, tree->left->reg2, tree->left->reg1);
2157 x86_shift_reg (s->code, X86_SHL, tree->left->reg1);
2158 x86_test_reg_imm (s->code, X86_ECX, 32);
2159 o1 = 2 + s->code - s->start;
2160 x86_branch8 (s->code, X86_CC_EQ, o2 - o1, FALSE);
2161 x86_mov_reg_reg (s->code, tree->left->reg2, tree->left->reg1, 4);
2162 x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->left->reg1);
2163 o2 = s->code - s->start;
2166 if (tree->reg1 != tree->left->reg1)
2167 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2168 if (tree->reg2 != tree->left->reg2)
2169 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2172 lreg: ADD (lreg, lreg) {
2173 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
2174 x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
2176 if (tree->reg1 != tree->left->reg1)
2177 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2178 if (tree->reg2 != tree->left->reg2)
2179 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2182 lreg: ADD_OVF (lreg, lreg) {
2183 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
2184 x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
2185 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
2187 if (tree->reg1 != tree->left->reg1)
2188 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2189 if (tree->reg2 != tree->left->reg2)
2190 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2193 lreg: ADD_OVF_UN (lreg, lreg) {
2194 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
2195 x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
2196 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
2198 if (tree->reg1 != tree->left->reg1)
2199 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2200 if (tree->reg2 != tree->left->reg2)
2201 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2204 lreg: SUB (lreg, lreg) {
2205 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
2206 x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
2208 if (tree->reg1 != tree->left->reg1)
2209 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2210 if (tree->reg2 != tree->left->reg2)
2211 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2214 lreg: SUB_OVF (lreg, lreg) {
2215 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
2216 x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
2217 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
2219 if (tree->reg1 != tree->left->reg1)
2220 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2221 if (tree->reg2 != tree->left->reg2)
2222 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2225 lreg: SUB_OVF_UN (lreg, lreg) {
2226 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
2227 x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
2228 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
2230 if (tree->reg1 != tree->left->reg1)
2231 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2232 if (tree->reg2 != tree->left->reg2)
2233 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2236 lreg: AND (lreg, lreg) {
2237 x86_alu_reg_reg (s->code, X86_AND, tree->left->reg1, tree->right->reg1);
2238 x86_alu_reg_reg (s->code, X86_AND, tree->left->reg2, tree->right->reg2);
2240 if (tree->reg1 != tree->left->reg1)
2241 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2242 if (tree->reg2 != tree->left->reg2)
2243 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2246 lreg: OR (lreg, lreg) {
2247 x86_alu_reg_reg (s->code, X86_OR, tree->left->reg1, tree->right->reg1);
2248 x86_alu_reg_reg (s->code, X86_OR, tree->left->reg2, tree->right->reg2);
2250 if (tree->reg1 != tree->left->reg1)
2251 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2252 if (tree->reg2 != tree->left->reg2)
2253 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2257 if (tree->reg1 != tree->left->reg1)
2258 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2259 if (tree->reg2 != tree->left->reg2)
2260 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2262 x86_neg_reg (s->code, tree->reg1);
2263 x86_alu_reg_imm (s->code, X86_ADC, tree->reg2, 0);
2264 x86_neg_reg (s->code, tree->reg2);
2268 if (tree->reg1 != tree->left->reg1)
2269 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2270 if (tree->reg2 != tree->left->reg2)
2271 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
2273 x86_not_reg (s->code, tree->reg1);
2274 x86_not_reg (s->code, tree->reg2);
2277 lreg: MUL (lreg, lreg) {
2278 if (mono_regset_reg_used (s->rs, X86_ECX))
2279 x86_push_reg (s->code, X86_ECX);
2281 x86_push_reg (s->code, tree->right->reg2);
2282 x86_push_reg (s->code, tree->right->reg1);
2283 x86_push_reg (s->code, tree->left->reg2);
2284 x86_push_reg (s->code, tree->left->reg1);
2285 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_llmult);
2286 x86_call_code (s->code, 0);
2287 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2289 if (mono_regset_reg_used (s->rs, X86_ECX))
2290 x86_pop_reg (s->code, X86_ECX);
2292 mono_assert (tree->reg1 == X86_EAX &&
2293 tree->reg2 == X86_EDX);
2296 lreg: MUL_OVF (lreg, lreg) {
2297 if (mono_regset_reg_used (s->rs, X86_ECX))
2298 x86_push_reg (s->code, X86_ECX);
2300 x86_push_reg (s->code, tree->right->reg2);
2301 x86_push_reg (s->code, tree->right->reg1);
2302 x86_push_reg (s->code, tree->left->reg2);
2303 x86_push_reg (s->code, tree->left->reg1);
2304 /* pass a pointer to store the resulting exception -
2305 * ugly, but it works */
2306 x86_push_reg (s->code, X86_ESP);
2307 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_llmult_ovf);
2308 x86_call_code (s->code, 0);
2309 x86_mov_reg_membase (s->code, X86_ECX, X86_ESP, 4, 4);
2310 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
2311 x86_alu_reg_imm (s->code, X86_CMP, X86_ECX, 0);
2313 /* cond. emit exception */
2314 x86_branch8 (s->code, X86_CC_EQ, 7, FALSE);
2315 x86_push_reg (s->code, X86_ECX);
2316 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, arch_get_throw_exception ());
2317 x86_call_code (s->code, 0);
2319 if (mono_regset_reg_used (s->rs, X86_ECX))
2320 x86_pop_reg (s->code, X86_ECX);
2322 mono_assert (tree->reg1 == X86_EAX &&
2323 tree->reg2 == X86_EDX);
2326 lreg: MUL_OVF_UN (lreg, lreg) {
2327 if (mono_regset_reg_used (s->rs, X86_ECX))
2328 x86_push_reg (s->code, X86_ECX);
2330 x86_push_reg (s->code, tree->right->reg2);
2331 x86_push_reg (s->code, tree->right->reg1);
2332 x86_push_reg (s->code, tree->left->reg2);
2333 x86_push_reg (s->code, tree->left->reg1);
2334 /* pass a pointer to store the resulting exception -
2335 * ugly, but it works */
2336 x86_push_reg (s->code, X86_ESP);
2337 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_llmult_ovf_un);
2338 x86_call_code (s->code, 0);
2339 x86_mov_reg_membase (s->code, X86_ECX, X86_ESP, 4, 4);
2340 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
2341 x86_alu_reg_imm (s->code, X86_CMP, X86_ECX, 0);
2343 /* cond. emit exception */
2344 x86_branch8 (s->code, X86_CC_EQ, 7, FALSE);
2345 x86_push_reg (s->code, X86_ECX);
2346 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, arch_get_throw_exception ());
2347 x86_call_code (s->code, 0);
2349 if (mono_regset_reg_used (s->rs, X86_ECX))
2350 x86_pop_reg (s->code, X86_ECX);
2352 mono_assert (tree->reg1 == X86_EAX &&
2353 tree->reg2 == X86_EDX);
2356 lreg: DIV (lreg, lreg) {
2357 if (mono_regset_reg_used (s->rs, X86_ECX))
2358 x86_push_reg (s->code, X86_ECX);
2360 x86_push_reg (s->code, tree->right->reg2);
2361 x86_push_reg (s->code, tree->right->reg1);
2362 x86_push_reg (s->code, tree->left->reg2);
2363 x86_push_reg (s->code, tree->left->reg1);
2364 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_lldiv);
2365 x86_call_code (s->code, 0);
2366 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2368 if (mono_regset_reg_used (s->rs, X86_ECX))
2369 x86_pop_reg (s->code, X86_ECX);
2371 mono_assert (tree->reg1 == X86_EAX &&
2372 tree->reg2 == X86_EDX);
2375 lreg: REM (lreg, lreg) {
2376 if (mono_regset_reg_used (s->rs, X86_ECX))
2377 x86_push_reg (s->code, X86_ECX);
2379 x86_push_reg (s->code, tree->right->reg2);
2380 x86_push_reg (s->code, tree->right->reg1);
2381 x86_push_reg (s->code, tree->left->reg2);
2382 x86_push_reg (s->code, tree->left->reg1);
2383 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_llrem);
2384 x86_call_code (s->code, 0);
2385 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2387 if (mono_regset_reg_used (s->rs, X86_ECX))
2388 x86_pop_reg (s->code, X86_ECX);
2390 mono_assert (tree->reg1 == X86_EAX &&
2391 tree->reg2 == X86_EDX);
2394 lreg: DIV_UN (lreg, lreg) {
2395 if (mono_regset_reg_used (s->rs, X86_ECX))
2396 x86_push_reg (s->code, X86_ECX);
2398 x86_push_reg (s->code, tree->right->reg2);
2399 x86_push_reg (s->code, tree->right->reg1);
2400 x86_push_reg (s->code, tree->left->reg2);
2401 x86_push_reg (s->code, tree->left->reg1);
2402 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_lldiv_un);
2403 x86_call_code (s->code, 0);
2404 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2406 if (mono_regset_reg_used (s->rs, X86_ECX))
2407 x86_pop_reg (s->code, X86_ECX);
2409 mono_assert (tree->reg1 == X86_EAX &&
2410 tree->reg2 == X86_EDX);
2413 lreg: REM_UN (lreg, lreg) {
2414 if (mono_regset_reg_used (s->rs, X86_ECX))
2415 x86_push_reg (s->code, X86_ECX);
2417 x86_push_reg (s->code, tree->right->reg2);
2418 x86_push_reg (s->code, tree->right->reg1);
2419 x86_push_reg (s->code, tree->left->reg2);
2420 x86_push_reg (s->code, tree->left->reg1);
2421 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, mono_llrem_un);
2422 x86_call_code (s->code, 0);
2423 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
2425 if (mono_regset_reg_used (s->rs, X86_ECX))
2426 x86_pop_reg (s->code, X86_ECX);
2428 mono_assert (tree->reg1 == X86_EAX &&
2429 tree->reg2 == X86_EDX);
2432 lreg: CALL_I8 (this, ADDR_G) {
2433 MethodCallInfo *ci = tree->data.ci;
2434 int lreg = tree->left->reg1;
2440 if (tree->left->op != MB_TERM_NOP) {
2441 mono_assert (lreg >= 0);
2442 x86_push_reg (s->code, lreg);
2445 if (ci->vtype_num) {
2446 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
2447 x86_lea_membase (s->code, treg, X86_EBP, offset);
2448 x86_push_reg (s->code, treg);
2451 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, tree->right->data.p);
2452 x86_call_code (s->code, 0);
2455 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
2457 mono_assert (tree->reg1 == X86_EAX);
2458 mono_assert (tree->reg2 == X86_EDX);
2461 lreg: CALL_I8 (this, VFUNC_ADDR) {
2462 MethodCallInfo *ci = tree->data.ci;
2463 int lreg = tree->left->reg1;
2469 if (tree->left->op != MB_TERM_NOP) {
2470 mono_assert (lreg >= 0);
2471 x86_push_reg (s->code, lreg);
2474 if (ci->vtype_num) {
2475 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
2476 x86_lea_membase (s->code, treg, X86_EBP, offset);
2477 x86_push_reg (s->code, treg);
2480 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2481 x86_call_virtual (s->code, lreg,
2482 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
2485 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
2487 PRINT_REG ("CALL0_I8(VIRTUAL)", tree->reg1);
2488 PRINT_REG ("CALL1_I8(VIRTUAL)", tree->reg2);
2490 mono_assert (tree->reg1 == X86_EAX);
2491 mono_assert (tree->reg2 == X86_EDX);
2494 lreg: CALL_I8 (this, INTF_ADDR) {
2495 MethodCallInfo *ci = tree->data.ci;
2496 int lreg = tree->left->reg1;
2502 if (tree->left->op != MB_TERM_NOP) {
2503 mono_assert (lreg >= 0);
2504 x86_push_reg (s->code, lreg);
2507 if (ci->vtype_num) {
2508 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
2509 x86_lea_membase (s->code, treg, X86_EBP, offset);
2510 x86_push_reg (s->code, treg);
2513 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2514 x86_mov_reg_membase (s->code, lreg, lreg,
2515 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
2516 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
2517 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
2520 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
2522 PRINT_REG ("CALL_I8(INTERFACE)", tree->reg1);
2524 mono_assert (tree->reg1 == X86_EAX);
2525 mono_assert (tree->reg2 == X86_EDX);
2529 if (tree->left->reg1 != X86_EAX) {
2530 if (tree->left->reg2 != X86_EAX) {
2531 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
2532 if (tree->left->reg2 != X86_EDX)
2533 x86_mov_reg_reg (s->code, X86_EDX, tree->left->reg2, 4);
2535 x86_mov_reg_reg (s->code, X86_ECX, tree->left->reg2, 4);
2536 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
2537 x86_mov_reg_reg (s->code, X86_EDX, X86_ECX, 4);
2539 } else if (tree->left->reg2 != X86_EDX) {
2540 x86_mov_reg_reg (s->code, X86_EDX, tree->left->reg2, 4);
2543 if (!tree->last_instr) {
2544 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_EPILOG, NULL);
2545 x86_jump32 (s->code, 0);
2550 stmt: ARG_I8 (lreg) {
2551 x86_push_reg (s->code, tree->left->reg2);
2552 x86_push_reg (s->code, tree->left->reg1);
2555 reg: CEQ (lreg, lreg) {
2556 guint8 *start = s->code;
2559 for (i = 0; i < 2; i ++) {
2561 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2562 o1 = 2 + s->code - s->start;
2563 x86_branch8 (s->code, X86_CC_NE, o2 - o1, FALSE);
2564 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2565 o2 = s->code - s->start;
2566 x86_set_reg (s->code, X86_CC_EQ, tree->reg1, FALSE);
2567 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
2571 reg: CLT (lreg, lreg) {
2572 guint8 *start = s->code;
2573 gpointer o1, o2, o3, o4, o5;
2576 for (i = 0; i < 2; i ++) {
2578 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2579 x86_branch8 (s->code, X86_CC_GT, o4 - o1, TRUE);
2581 x86_branch8 (s->code, X86_CC_NE, o4 - o2, TRUE);
2583 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2584 x86_branch8 (s->code, X86_CC_GE, o4 - o3, FALSE);
2586 /* set result to 1 */
2588 x86_mov_reg_imm (s->code, tree->reg1, 1);
2589 x86_jump8 (s->code, (o4 - o3));
2590 /* set result to 0 */
2592 x86_mov_reg_imm (s->code, tree->reg1, 0);
2597 stmt: BEQ (lreg, lreg) {
2598 guint8 *start = s->code;
2602 for (i = 0; i < 2; i ++) {
2604 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2605 x86_branch8 (s->code, X86_CC_NE, o2 - o1, FALSE);
2607 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2608 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2609 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
2614 stmt: BNE_UN (lreg, lreg) {
2615 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2616 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2617 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
2618 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2619 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2620 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
2623 stmt: BGE (lreg, lreg) {
2624 guint8 *start = s->code;
2628 for (i = 0; i < 2; i ++) {
2630 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2631 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2632 x86_branch32 (s->code, X86_CC_GT, 0, TRUE);
2633 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2634 x86_branch8 (s->code, X86_CC_NE, oe - o2, TRUE);
2636 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2637 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2638 x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
2643 stmt: BGE_UN (lreg, lreg) {
2644 guint8 *start = s->code;
2648 for (i = 0; i < 2; i ++) {
2650 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2651 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2652 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
2653 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2654 x86_branch8 (s->code, X86_CC_NE, oe - o2, FALSE);
2656 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2657 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2658 x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
2663 stmt: BGT (lreg, lreg) {
2664 guint8 *start = s->code;
2668 for (i = 0; i < 2; i ++) {
2670 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2671 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2672 x86_branch32 (s->code, X86_CC_GT, 0, TRUE);
2673 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2674 x86_branch8 (s->code, X86_CC_NE, oe - o2, TRUE);
2676 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2677 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2678 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
2683 stmt: BGT_UN (lreg, lreg) {
2684 guint8 *start = s->code;
2688 for (i = 0; i < 2; i ++) {
2690 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2691 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2692 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
2693 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2694 x86_branch8 (s->code, X86_CC_NE, oe - o2, FALSE);
2696 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2697 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2698 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
2703 stmt: BLT (lreg, lreg) {
2704 guint8 *start = s->code;
2708 for (i = 0; i < 2; i ++) {
2710 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2711 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2712 x86_branch32 (s->code, X86_CC_LT, 0, TRUE);
2713 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2714 x86_branch8 (s->code, X86_CC_NE, oe - o2, TRUE);
2716 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2717 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2718 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
2723 stmt: BLT_UN (lreg, lreg) {
2724 guint8 *start = s->code;
2728 for (i = 0; i < 2; i ++) {
2730 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2731 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2732 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
2733 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2734 x86_branch8 (s->code, X86_CC_NE, oe - o2, FALSE);
2736 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2737 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2738 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
2743 stmt: BLE (lreg, lreg) {
2744 guint8 *start = s->code;
2748 for (i = 0; i < 2; i ++) {
2750 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2751 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2752 x86_branch32 (s->code, X86_CC_LT, 0, TRUE);
2753 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2754 x86_branch8 (s->code, X86_CC_NE, oe - o2, TRUE);
2756 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2757 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2758 x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
2763 stmt: BLE_UN (lreg, lreg) {
2764 guint8 *start = s->code;
2768 for (i = 0; i < 2; i ++) {
2770 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2771 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2772 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
2773 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
2774 x86_branch8 (s->code, X86_CC_NE, oe - o2, FALSE);
2776 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2777 if (i) mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
2778 x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
2786 #stmt: STLOC (CONV_I4 (freg)) {
2788 # x86_fist_pop_membase (s->code, X86_EBP, tree->data.i, FALSE);
2791 reg: CONV_I1 (freg) {
2792 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
2793 x86_fnstcw_membase(s->code, X86_ESP, 0);
2794 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
2795 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
2796 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
2797 x86_fldcw_membase (s->code, X86_ESP, 2);
2798 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
2799 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
2800 x86_pop_reg (s->code, tree->reg1);
2801 x86_widen_reg (s->code, tree->reg1, tree->reg1, TRUE, FALSE);
2802 x86_fldcw_membase (s->code, X86_ESP, 0);
2803 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
2806 reg: CONV_I2 (freg) {
2807 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
2808 x86_fnstcw_membase(s->code, X86_ESP, 0);
2809 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
2810 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
2811 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
2812 x86_fldcw_membase (s->code, X86_ESP, 2);
2813 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
2814 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
2815 x86_pop_reg (s->code, tree->reg1);
2816 x86_widen_reg (s->code, tree->reg1, tree->reg1, TRUE, TRUE);
2817 x86_fldcw_membase (s->code, X86_ESP, 0);
2818 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
2821 reg: CONV_I4 (freg) {
2822 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
2823 x86_fnstcw_membase(s->code, X86_ESP, 0);
2824 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
2825 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
2826 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
2827 x86_fldcw_membase (s->code, X86_ESP, 2);
2828 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
2829 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
2830 x86_pop_reg (s->code, tree->reg1);
2831 x86_fldcw_membase (s->code, X86_ESP, 0);
2832 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
2835 lreg: CONV_I8 (freg) {
2836 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
2837 x86_fnstcw_membase(s->code, X86_ESP, 0);
2838 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
2839 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
2840 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
2841 x86_fldcw_membase (s->code, X86_ESP, 2);
2842 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
2843 x86_fist_pop_membase (s->code, X86_ESP, 0, TRUE);
2844 x86_pop_reg (s->code, tree->reg1);
2845 x86_pop_reg (s->code, tree->reg2);
2846 x86_fldcw_membase (s->code, X86_ESP, 0);
2847 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
2850 reg: CEQ (freg, freg) {
2851 int treg = tree->reg1;
2853 if (treg != X86_EAX)
2854 x86_push_reg (s->code, X86_EAX); // save EAX
2856 x86_fcompp (s->code);
2857 x86_fnstsw (s->code);
2858 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
2859 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
2860 x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
2861 x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
2863 if (treg != X86_EAX)
2864 x86_pop_reg (s->code, X86_EAX); // save EAX
2867 freg: CONV_R8 (freg) {
2871 freg: CONV_R4 (freg) {
2872 /* fixme: nothing to do ??*/
2875 freg: CONV_R8 (LDIND_I4 (ADDR_G)) {
2876 x86_fild (s->code, tree->left->left->data.p, FALSE);
2879 freg: CONV_R4 (reg) {
2880 x86_push_reg (s->code, tree->left->reg1);
2881 x86_fild_membase (s->code, X86_ESP, 0, FALSE);
2882 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
2885 freg: CONV_R8 (reg) {
2886 x86_push_reg (s->code, tree->left->reg1);
2887 x86_fild_membase (s->code, X86_ESP, 0, FALSE);
2888 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
2891 freg: CONV_R_UN (reg) {
2892 x86_push_imm (s->code, 0);
2893 x86_push_reg (s->code, tree->left->reg1);
2894 x86_fild_membase (s->code, X86_ESP, 0, TRUE);
2895 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
2898 freg: CONV_R_UN (lreg) {
2899 guint8 *start = s->code, *l1, *l2;
2902 static guint8 mn[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x40 };
2904 for (i = 0; i < 2; i++) {
2907 /* load 64bit integer to FP stack */
2908 x86_push_imm (s->code, 0);
2909 x86_push_reg (s->code, tree->left->reg2);
2910 x86_push_reg (s->code, tree->left->reg1);
2911 x86_fild_membase (s->code, X86_ESP, 0, TRUE);
2912 /* store as 80bit FP value */
2913 x86_fst80_membase (s->code, X86_ESP, 0);
2915 /* test if lreg is negative */
2916 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
2917 x86_branch8 (s->code, X86_CC_GEZ, l2 - l1, TRUE);
2920 /* add correction constant mn */
2921 x86_fld80_mem (s->code, mn);
2922 x86_fld80_membase (s->code, X86_ESP, 0);
2923 x86_fp_op_reg (s->code, X86_FADD, 1, TRUE);
2924 x86_fst80_membase (s->code, X86_ESP, 0);
2928 x86_fld80_membase (s->code, X86_ESP, 0);
2929 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 12);
2933 freg: CONV_R4 (lreg) {
2934 x86_push_reg (s->code, tree->left->reg2);
2935 x86_push_reg (s->code, tree->left->reg1);
2936 x86_fild_membase (s->code, X86_ESP, 0, TRUE);
2937 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
2940 freg: CONV_R8 (lreg) {
2941 x86_push_reg (s->code, tree->left->reg2);
2942 x86_push_reg (s->code, tree->left->reg1);
2943 x86_fild_membase (s->code, X86_ESP, 0, TRUE);
2944 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
2948 float f = *(float *)tree->data.p;
2955 x86_fld (s->code, tree->data.p, FALSE);
2959 double d = *(double *)tree->data.p;
2966 x86_fld (s->code, tree->data.p, TRUE);
2969 freg: LDIND_R4 (reg) {
2970 x86_fld_membase (s->code, tree->left->reg1, 0, FALSE);
2973 freg: LDIND_R8 (reg) {
2974 x86_fld_membase (s->code, tree->left->reg1, 0, TRUE);
2977 freg: ADD (freg, freg) {
2978 x86_fp_op_reg (s->code, X86_FADD, 1, TRUE);
2981 freg: SUB (freg, freg) {
2982 x86_fp_op_reg (s->code, X86_FSUB, 1, TRUE);
2985 freg: MUL (freg, freg) {
2986 x86_fp_op_reg (s->code, X86_FMUL, 1, TRUE);
2989 freg: DIV (freg, freg) {
2990 x86_fp_op_reg (s->code, X86_FDIV, 1, TRUE);
2993 #freg: REM (freg, freg) {
2994 # this does not work, since it does not pop a value from the stack,
2995 # and we need to test if the instruction is ready
2996 # x86_fprem1 (s->code);
3005 stmt: STIND_R4 (ADDR_L, freg) {
3006 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->left->data.i).offset;
3007 x86_fst_membase (s->code, X86_EBP, offset, FALSE, TRUE);
3010 stmt: STIND_R4 (reg, freg) {
3011 x86_fst_membase (s->code, tree->left->reg1, 0, FALSE, TRUE);
3014 stmt: STIND_R8 (ADDR_L, freg) {
3015 int offset = g_array_index (s->varinfo, MonoVarInfo, tree->left->data.i).offset;
3016 x86_fst_membase (s->code, X86_EBP, offset, TRUE, TRUE);
3019 stmt: STIND_R8 (reg, freg) {
3020 x86_fst_membase (s->code, tree->left->reg1, 0, TRUE, TRUE);
3023 stmt: ARG_R4 (freg) {
3024 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3025 x86_fst_membase (s->code, X86_ESP, 0, FALSE, TRUE);
3028 stmt: ARG_R8 (freg) {
3029 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
3030 x86_fst_membase (s->code, X86_ESP, 0, TRUE, TRUE);
3033 # fixme: we need to implement unordered and ordered compares
3035 stmt: BEQ (freg, freg) {
3036 x86_fcompp (s->code);
3037 x86_fnstsw (s->code);
3038 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3039 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
3040 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3041 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
3044 stmt: BNE_UN (freg, freg) {
3045 x86_fcompp (s->code);
3046 x86_fnstsw (s->code);
3047 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3048 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
3049 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3050 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3053 stmt: BLT (freg, freg) {
3054 x86_fcompp (s->code);
3055 x86_fnstsw (s->code);
3056 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3057 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3058 x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
3061 stmt: BLT_UN (freg, freg) {
3062 x86_fcompp (s->code);
3063 x86_fnstsw (s->code);
3064 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3065 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3066 x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
3069 stmt: BGE (freg, freg) {
3070 x86_fcompp (s->code);
3071 x86_fnstsw (s->code);
3072 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3073 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3074 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3077 stmt: BGE_UN (freg, freg) {
3078 x86_fcompp (s->code);
3079 x86_fnstsw (s->code);
3080 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3081 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3082 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3085 stmt: BGT (freg, freg) {
3086 x86_fcompp (s->code);
3087 x86_fnstsw (s->code);
3088 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3089 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3090 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3091 x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
3094 stmt: BGT_UN (freg, freg) {
3095 x86_fcompp (s->code);
3096 x86_fnstsw (s->code);
3097 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3098 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3099 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3100 x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
3103 stmt: BLE (freg, freg) {
3104 x86_fcompp (s->code);
3105 x86_fnstsw (s->code);
3106 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3107 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3108 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3109 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3112 stmt: BLE_UN (freg, freg) {
3113 x86_fcompp (s->code);
3114 x86_fnstsw (s->code);
3115 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
3116 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
3117 mono_add_jump_info (s, s->code + 2, MONO_JUMP_INFO_BB, tree->data.bb);
3118 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3121 freg: CALL_R8 (this, ADDR_G) {
3122 MethodCallInfo *ci = tree->data.ci;
3123 int lreg = tree->left->reg1;
3129 if (tree->left->op != MB_TERM_NOP) {
3130 mono_assert (lreg >= 0);
3131 x86_push_reg (s->code, lreg);
3134 if (ci->vtype_num) {
3135 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
3136 x86_lea_membase (s->code, treg, X86_EBP, offset);
3137 x86_push_reg (s->code, treg);
3140 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, tree->right->data.p);
3141 x86_call_code (s->code, 0);
3144 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
3147 freg: CALL_R8 (this, INTF_ADDR) {
3148 MethodCallInfo *ci = tree->data.ci;
3149 int lreg = tree->left->reg1;
3155 if (tree->left->op != MB_TERM_NOP) {
3156 mono_assert (lreg >= 0);
3157 x86_push_reg (s->code, lreg);
3160 if (ci->vtype_num) {
3161 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
3162 x86_lea_membase (s->code, treg, X86_EBP, offset);
3163 x86_push_reg (s->code, treg);
3166 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
3167 x86_mov_reg_membase (s->code, lreg, lreg,
3168 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
3169 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
3170 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
3173 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
3176 freg: CALL_R8 (this, VFUNC_ADDR) {
3177 MethodCallInfo *ci = tree->data.ci;
3178 int lreg = tree->left->reg1;
3184 if (tree->left->op != MB_TERM_NOP) {
3185 mono_assert (lreg >= 0);
3186 x86_push_reg (s->code, lreg);
3189 if (ci->vtype_num) {
3190 int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
3191 x86_lea_membase (s->code, treg, X86_EBP, offset);
3192 x86_push_reg (s->code, treg);
3195 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
3196 x86_call_virtual (s->code, lreg,
3197 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
3200 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
3204 if (!tree->last_instr) {
3205 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_EPILOG, NULL);
3206 x86_jump32 (s->code, 0);
3210 # support for value types
3212 reg: LDIND_OBJ (reg) {
3213 if (tree->left->reg1 != tree->reg1)
3214 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3217 stmt: STIND_OBJ (reg, reg) {
3218 x86_push_reg (s->code, X86_EAX);
3219 x86_push_reg (s->code, X86_EDX);
3220 x86_push_reg (s->code, X86_ECX);
3222 mono_assert (tree->data.i > 0);
3223 x86_push_imm (s->code, tree->data.i);
3224 x86_push_reg (s->code, tree->right->reg1);
3225 x86_push_reg (s->code, tree->left->reg1);
3226 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, MEMCOPY);
3227 x86_call_code (s->code, 0);
3228 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
3230 x86_pop_reg (s->code, X86_ECX);
3231 x86_pop_reg (s->code, X86_EDX);
3232 x86_pop_reg (s->code, X86_EAX);
3235 stmt: ARG_OBJ (CONST_I4) {
3236 x86_push_imm (s->code, tree->left->data.i);
3239 stmt: ARG_OBJ (reg) {
3240 int size = tree->data.i;
3243 mono_assert (size > 0);
3248 /* reserve space for the argument */
3249 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);
3251 x86_push_reg (s->code, X86_EAX);
3252 x86_push_reg (s->code, X86_EDX);
3253 x86_push_reg (s->code, X86_ECX);
3255 x86_push_imm (s->code, size);
3256 x86_push_reg (s->code, tree->left->reg1);
3257 x86_lea_membase (s->code, X86_EAX, X86_ESP, 5*4);
3258 x86_push_reg (s->code, X86_EAX);
3260 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, MEMCOPY);
3261 x86_call_code (s->code, 0);
3262 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
3264 x86_pop_reg (s->code, X86_ECX);
3265 x86_pop_reg (s->code, X86_EDX);
3266 x86_pop_reg (s->code, X86_EAX);
3269 stmt: RET_OBJ (reg) {
3270 int size = tree->data.i;
3272 x86_push_imm (s->code, size);
3273 x86_push_reg (s->code, tree->left->reg1);
3274 x86_push_membase (s->code, X86_EBP, 8);
3277 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_ABS, MEMCOPY);
3278 x86_call_code (s->code, 0);
3280 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
3282 if (!tree->last_instr) {
3283 mono_add_jump_info (s, s->code + 1, MONO_JUMP_INFO_EPILOG, NULL);
3284 x86_jump32 (s->code, 0);
3293 mono_llmult (gint64 a, gint64 b)
3299 mono_llmult_ovf_un (gpointer *exc, guint32 al, guint32 ah, guint32 bl, guint32 bh)
3303 // fixme: this is incredible slow
3306 goto raise_exception;
3308 res = (guint64)al * (guint64)bl;
3310 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
3312 if (t1 > 0xffffffff)
3313 goto raise_exception;
3315 res += ((guint64)t1) << 32;
3321 *exc = mono_get_exception_overflow ();
3326 mono_llmult_ovf (gpointer *exc, guint32 al, gint32 ah, guint32 bl, gint32 bh)
3330 // fixme: check for overflow
3332 res = (gint64)al * (gint64)bl;
3334 t1 = (gint64)ah * bl + al * (gint64)bh;
3336 res += ((gint64)t1) << 32;
3342 *exc = mono_get_exception_overflow ();
3347 mono_lldiv (gint64 a, gint64 b)
3353 mono_llrem (gint64 a, gint64 b)
3359 mono_lldiv_un (guint64 a, guint64 b)
3365 mono_llrem_un (guint64 a, guint64 b)
3371 mono_ctree_new (MonoMemPool *mp, int op, MBTree *left, MBTree *right)
3373 MBTree *t = mono_mempool_alloc0 (mp, sizeof (MBTree));
3381 t->svt = VAL_UNKNOWN;
3387 mono_ctree_new_leaf (MonoMemPool *mp, int op)
3389 return mono_ctree_new (mp, op, NULL, NULL);
3393 arch_get_lmf_addr (void)
3397 if ((lmf = TlsGetValue (lmf_thread_id)))
3400 lmf = g_malloc (sizeof (gpointer));
3403 TlsSetValue (lmf_thread_id, lmf);
3409 mono_array_new_wrapper (MonoClass *eclass, guint32 n)
3411 MonoDomain *domain = mono_domain_get ();
3413 return mono_array_new (domain, eclass, n);
3417 mono_object_new_wrapper (MonoClass *klass)
3419 MonoDomain *domain = mono_domain_get ();
3421 return mono_object_new (domain, klass);
3425 mono_string_new_wrapper (const char *text)
3427 MonoDomain *domain = mono_domain_get ();
3429 return mono_string_new (domain, text);
3433 mono_ldstr_wrapper (MonoImage *image, guint32 index)
3435 MonoDomain *domain = mono_domain_get ();
3437 return mono_ldstr (domain, image, index);
3441 mono_ldsflda (MonoClass *klass, int offset)
3443 MonoDomain *domain = mono_domain_get ();
3447 vt = mono_class_vtable (domain, klass);
3448 addr = (char*)(vt->data) + offset;
3455 MEMCOPY (void *dest, const void *src, size_t n)
3459 printf ("MEMCPY(%p to %p [%d]) ", src, dest, n);
3461 for (i = 0; i < l; i++)
3462 printf ("%02x ", *((guint8 *)src + i));
3465 return memcpy (dest, src, n);