2 * x86.brg: X86 code generator
5 * Dietmar Maurer (dietmar@ximian.com)
7 * (C) 2001 Ximian, Inc.
16 #ifndef PLATFORM_WIN32
18 #include <sys/syscall.h>
21 #include <mono/metadata/blob.h>
22 #include <mono/metadata/metadata.h>
23 #include <mono/metadata/loader.h>
24 #include <mono/metadata/object.h>
25 #include <mono/metadata/tabledefs.h>
26 #include <mono/metadata/appdomain.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/arch/x86/x86-codegen.h>
34 * Pull the list of opcodes
36 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
40 #include "mono/cil/opcode.def"
45 /* alignment of activation frames */
46 #define MONO_FRAME_ALIGNMENT 4
48 void print_lmf (void);
50 #define MBTREE_TYPE MBTree
51 #define MBCGEN_TYPE MonoFlowGraph
52 #define MBCOST_DATA MonoFlowGraph
53 #define MBALLOC_STATE mono_mempool_alloc (data->mp, sizeof (MBState))
56 AMImmediate = 0, // ptr
58 AMIndex = 2, // V[REG*X]
59 AMBaseIndex = 3, // V[REG*X][REG]
72 unsigned last_instr:1;
95 MonoClassField *field;
99 MonoJitCallInfo call_info;
100 MonoJitArgumentInfo arg_info;
104 gint64 mono_llmult (gint64 a, gint64 b);
105 guint64 mono_llmult_ovf (gpointer *exc, guint32 al, gint32 ah, guint32 bl, gint32 bh);
106 guint64 mono_llmult_ovf_un (gpointer *exc, guint32 al, guint32 ah, guint32 bl, guint32 bh);
107 gint64 mono_lldiv (gint64 a, gint64 b);
108 gint64 mono_llrem (gint64 a, gint64 b);
109 guint64 mono_lldiv_un (guint64 a, guint64 b);
110 guint64 mono_llrem_un (guint64 a, guint64 b);
111 gpointer mono_ldsflda (MonoClass *klass, int offset);
113 gpointer mono_ldvirtftn (MonoObject *this, int slot);
114 gpointer mono_ldintftn (MonoObject *this, int slot);
115 gpointer mono_ldftn (MonoMethod *method);
117 void mono_emit_fast_iconv (MBCGEN_TYPE* s, MBTREE_TYPE* tree);
118 void mono_emit_fast_iconv_i8 (MBCGEN_TYPE* s, MBTREE_TYPE* tree);
119 void mono_emit_stack_alloc (MBCGEN_TYPE* s, MBTREE_TYPE* tree);
120 void mono_emit_stack_alloc_const (MBCGEN_TYPE* s, MBTREE_TYPE* tree, int size);
123 mono_array_new_wrapper (MonoClass *eclass, guint32 n);
125 mono_object_new_wrapper (MonoClass *klass);
127 mono_ldstr_wrapper (MonoImage *image, guint32 ind);
130 get_mono_object_isinst (void);
132 #define MB_OPT_LEVEL 1
134 #if MB_OPT_LEVEL == 0
135 #define MB_USE_OPT1(c) 65535
136 #define MB_USE_OPT2(c) 65535
138 #if MB_OPT_LEVEL == 1
139 #define MB_USE_OPT1(c) c
140 #define MB_USE_OPT2(c) 65535
142 #if MB_OPT_LEVEL >= 2
143 #define MB_USE_OPT1(c) c
144 #define MB_USE_OPT2(c) c
149 #define REAL_PRINT_REG(text,reg) \
150 mono_assert (reg >= 0); \
151 x86_push_reg (s->code, X86_EAX); \
152 x86_push_reg (s->code, X86_EDX); \
153 x86_push_reg (s->code, X86_ECX); \
154 x86_push_reg (s->code, reg); \
155 x86_push_imm (s->code, reg); \
156 x86_push_imm (s->code, text " %d %p\n"); \
157 x86_mov_reg_imm (s->code, X86_EAX, printf); \
158 x86_call_reg (s->code, X86_EAX); \
159 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 3*4); \
160 x86_pop_reg (s->code, X86_ECX); \
161 x86_pop_reg (s->code, X86_EDX); \
162 x86_pop_reg (s->code, X86_EAX);
165 debug_memcopy (void *dest, const void *src, size_t n);
168 #define MEMCOPY debug_memcopy
169 #define PRINT_REG(text,reg) REAL_PRINT_REG(text,reg)
172 #define MEMCOPY memcpy
174 #define PRINT_REG(x,y)
178 /* The call instruction for virtual functions must have a known
179 * size (used by x86_magic_trampoline)
181 #define x86_call_virtual(inst,basereg,disp) \
183 *(inst)++ = (unsigned char)0xff; \
184 x86_address_byte ((inst), 2, 2, (basereg)); \
185 x86_imm_emit32 ((inst), (disp)); \
188 /* emit an exception if condition is fail */
189 #define EMIT_COND_SYSTEM_EXCEPTION(cond,signed,exc_name) \
192 x86_branch8 (s->code, cond, 10, signed); \
193 x86_push_imm (s->code, exc_name); \
194 t = arch_get_throw_exception_by_name (); \
195 mono_add_jump_info (s, s->code, \
196 MONO_JUMP_INFO_ABS, t); \
197 x86_call_code (s->code, 0); \
200 #define X86_ARG_PAD(pad) do { \
203 x86_push_reg (s->code, X86_EAX); \
205 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, pad); \
209 #define X86_CALL_END do { \
210 int size = tree->data.call_info.frame_size; \
212 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, size); \
215 #define X86_CALL_BEGIN do { \
216 int pad = tree->data.call_info.pad; \
218 if (tree->left->op != MB_TERM_NOP) { \
219 mono_assert (lreg >= 0); \
220 x86_push_reg (s->code, lreg); \
221 x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0); \
223 if (tree->data.call_info.vtype_num) { \
224 int offset = VARINFO (s, tree->data.call_info.vtype_num).offset; \
225 x86_lea_membase (s->code, treg, X86_EBP, offset); \
226 x86_push_reg (s->code, treg); \
230 /* we use this macro to move one lreg to another - source and
231 destination may overlap, but the register allocator has to
232 make sure that ((d1 < d2) && (s1 < s2))
234 #define MOVE_LREG(d1,d2,s1,s2) \
236 g_assert ((d1 < d2) && (s1 < s2)); \
237 if ((d1) <= (s1)) { \
239 x86_mov_reg_reg (s->code, d1, s1, 4); \
241 x86_mov_reg_reg (s->code, d2, s2, 4); \
244 x86_mov_reg_reg (s->code, d2, s2, 4); \
246 x86_mov_reg_reg (s->code, d1, s1, 4); \
254 # terminal definitions
258 %term CONST_I4 CONST_I8 CONST_R4 CONST_R8
259 %term LDIND_I1 LDIND_U1 LDIND_I2 LDIND_U2 LDIND_I4 LDIND_I8 LDIND_R4 LDIND_R8 LDIND_OBJ
260 %term STIND_I1 STIND_I2 STIND_I4 STIND_I8 STIND_R4 STIND_R8 STIND_OBJ
261 %term ADDR_L ADDR_G ARG_I4 ARG_I8 ARG_R4 ARG_R8 ARG_OBJ CALL_I4 CALL_I8 CALL_R8 CALL_VOID
262 %term BREAK SWITCH BR RET_VOID RET RET_OBJ ENDFINALLY ENDFILTER JMP
263 %term ADD ADD_OVF ADD_OVF_UN SUB SUB_OVF SUB_OVF_UN MUL MUL_OVF MUL_OVF_UN
264 %term DIV DIV_UN REM REM_UN AND OR XOR SHL SHR SHR_UN NEG NOT CKFINITE
265 %term COMPARE CBRANCH BRTRUE BRFALSE CSET
266 %term CONV_I4 CONV_I1 CONV_I2 CONV_I8 CONV_U1 CONV_U2 CONV_U4 CONV_U8 CONV_R4 CONV_R8 CONV_R_UN
267 %term INTF_ADDR VFUNC_ADDR NOP NEWARR NEWARR_SPEC NEWOBJ NEWOBJ_SPEC
268 %term INITBLK CPBLK CPSRC POP INITOBJ LOCALLOC
269 %term ISINST CASTCLASS UNBOX
270 %term CONV_OVF_I1 CONV_OVF_U1 CONV_OVF_I2 CONV_OVF_U2 CONV_OVF_U4 CONV_OVF_U8 CONV_OVF_I4
271 %term CONV_OVF_I4_UN CONV_OVF_U1_UN CONV_OVF_U2_UN
272 %term CONV_OVF_I2_UN CONV_OVF_I8_UN CONV_OVF_I1_UN
273 %term EXCEPTION THROW RETHROW HANDLER CHECKTHIS
274 %term LDLEN LDELEMA LDFTN LDVIRTFTN LDSTR LDSFLDA
275 %term REMOTE_LDFLDA REMOTE_STIND_I1 REMOTE_STIND_I2 REMOTE_STIND_I4
276 %term REMOTE_STIND_I8 REMOTE_STIND_R4 REMOTE_STIND_R8 REMOTE_STIND_OBJ
279 %term FUNC1 PROC2 PROC3 FREE OBJADDR VTADDR
295 tree->data.ainfo.offset = tree->data.i;
296 tree->data.ainfo.amode = AMImmediate;
300 tree->data.ainfo.offset = tree->data.i;
301 tree->data.ainfo.amode = AMImmediate;
304 acon: ADD (ADDR_G, CONST_I4) {
305 tree->data.ainfo.offset = (unsigned)tree->left->data.p + tree->right->data.i;
306 tree->data.ainfo.amode = AMImmediate;
312 tree->data.ainfo.offset = 0;
313 tree->data.ainfo.basereg = tree->reg1;
314 tree->data.ainfo.amode = AMBase;
317 base: ADD (reg, CONST_I4) {
318 tree->data.ainfo.offset = tree->right->data.i;
319 tree->data.ainfo.basereg = tree->left->reg1;
320 tree->data.ainfo.amode = AMBase;
324 tree->data.ainfo.offset = VARINFO (s, tree->data.i).offset;
325 tree->data.ainfo.basereg = X86_EBP;
326 tree->data.ainfo.amode = AMBase;
328 MBCOND (VARINFO (data, tree->data.i).reg < 0);
333 tree->data.ainfo.offset = 0;
334 tree->data.ainfo.indexreg = tree->reg1;
335 tree->data.ainfo.shift = 0;
336 tree->data.ainfo.amode = AMIndex;
339 index: SHL (reg, CONST_I4) {
340 tree->data.ainfo.offset = 0;
341 tree->data.ainfo.amode = AMIndex;
342 tree->data.ainfo.indexreg = tree->left->reg1;
343 tree->data.ainfo.shift = tree->right->data.i;
345 MBCOND (tree->right->data.i == 0 ||
346 tree->right->data.i == 1 ||
347 tree->right->data.i == 2 ||
348 tree->right->data.i == 3);
353 index: MUL (reg, CONST_I4) {
354 static int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
356 tree->data.ainfo.offset = 0;
357 tree->data.ainfo.amode = AMIndex;
358 tree->data.ainfo.indexreg = tree->left->reg1;
359 tree->data.ainfo.shift = fast_log2 [tree->right->data.i];
361 MBCOND (tree->right->data.i == 1 ||
362 tree->right->data.i == 2 ||
363 tree->right->data.i == 4 ||
364 tree->right->data.i == 8);
373 addr: ADD (index, base) {
374 tree->data.ainfo.offset = tree->right->data.ainfo.offset;
375 tree->data.ainfo.basereg = tree->right->data.ainfo.basereg;
376 tree->data.ainfo.amode = tree->left->data.ainfo.amode |
377 tree->right->data.ainfo.amode;
378 tree->data.ainfo.shift = tree->left->data.ainfo.shift;
379 tree->data.ainfo.indexreg = tree->left->data.ainfo.indexreg;
382 # we pass exception in ECX to catch handler
384 int offset = VARINFO (s, tree->data.i).offset;
386 if (tree->reg1 != X86_ECX)
387 x86_mov_reg_reg (s->code, tree->reg1, X86_ECX, 4);
389 /* store it so that we can RETHROW it later */
390 x86_mov_membase_reg (s->code, X86_EBP, offset, tree->reg1, 4);
396 x86_push_reg (s->code, tree->left->reg1);
397 target = arch_get_throw_exception ();
398 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, target);
399 x86_call_code (s->code, target);
403 int offset = VARINFO (s, tree->data.i).offset;
406 x86_push_membase (s->code, X86_EBP, offset);
408 target = arch_get_throw_exception ();
409 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, target);
410 x86_call_code (s->code, target);
414 /* save ESP (used by ENDFINALLY) */
415 x86_mov_membase_reg (s->code, X86_EBP, mono_exc_esp_offset, X86_ESP, 4);
416 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bb);
417 x86_call_imm (s->code, 0);
421 /* restore ESP - which can be modified when we allocate value types
422 * in the finally handler */
423 x86_mov_reg_membase (s->code, X86_ESP, X86_EBP, mono_exc_esp_offset, 4);
424 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
428 stmt: ENDFILTER (reg) {
429 /* restore ESP - which can be modified when we allocate value types
431 x86_mov_reg_membase (s->code, X86_ESP, X86_EBP, mono_exc_esp_offset, 4);
432 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
433 if (tree->left->reg1 != X86_EAX)
434 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
438 stmt: STIND_I4 (ADDR_L, ADD (LDIND_I4 (ADDR_L), CONST_I4)) {
439 int vn = tree->left->data.i;
440 int treg = VARINFO (s, vn).reg;
441 int offset = VARINFO (s, vn).offset;
442 int data = tree->right->right->data.i;
446 x86_inc_reg (s->code, treg);
448 x86_inc_membase (s->code, X86_EBP, offset);
451 x86_alu_reg_imm (s->code, X86_ADD, treg, data);
453 x86_alu_membase_imm (s->code, X86_ADD, X86_EBP, offset, data);
456 MBCOND (tree->right->left->left->data.i == tree->left->data.i);
460 stmt: STIND_I4 (ADDR_L, SUB (LDIND_I4 (ADDR_L), CONST_I4)) {
461 int vn = tree->left->data.i;
462 int treg = VARINFO (s, vn).reg;
463 int offset = VARINFO (s, vn).offset;
464 int data = tree->right->right->data.i;
468 x86_dec_reg (s->code, treg);
470 x86_dec_membase (s->code, X86_EBP, offset);
473 x86_alu_reg_imm (s->code, X86_SUB, treg, data);
475 x86_alu_membase_imm (s->code, X86_SUB, X86_EBP, offset, data);
478 MBCOND (tree->right->left->left->data.i == tree->left->data.i);
482 stmt: STIND_I4 (ADDR_L, ADD (LDIND_I4 (ADDR_L), reg)) {
483 int vn = tree->left->data.i;
484 int treg = VARINFO (s, vn).reg;
485 int sreg = tree->right->right->reg1;
486 int offset = VARINFO (s, vn).offset;
489 x86_alu_reg_reg (s->code, X86_ADD, treg, sreg);
491 x86_alu_membase_reg (s->code, X86_ADD, X86_EBP, offset, sreg);
494 MBCOND (tree->right->left->left->data.i == tree->left->data.i);
498 stmt: STIND_I4 (ADDR_L, LDIND_I4 (ADDR_L)) {
499 int treg1 = VARINFO (s, tree->left->data.i).reg;
500 int treg2 = VARINFO (s, tree->right->left->data.i).reg;
501 int offset1 = VARINFO (s, tree->left->data.i).offset;
502 int offset2 = VARINFO (s, tree->right->left->data.i).offset;
504 //{static int cx= 0; printf ("CX %5d\n", cx++);}
506 if (treg1 >= 0 && treg2 >= 0) {
507 x86_mov_reg_reg (s->code, treg1, treg2, 4);
510 if (treg1 >= 0 && treg2 < 0) {
511 x86_mov_reg_membase (s->code, treg1, X86_EBP, offset2, 4);
514 if (treg1 < 0 && treg2 >= 0) {
515 x86_mov_membase_reg (s->code, X86_EBP, offset1, treg2, 4);
519 g_assert_not_reached ();
522 MBCOND (VARINFO (data, tree->left->data.i).reg >= 0 ||
523 VARINFO (data, tree->right->left->data.i).reg >= 0);
527 stmt: STIND_I4 (addr, CONST_I4) {
528 switch (tree->left->data.ainfo.amode) {
531 x86_mov_mem_imm (s->code, tree->left->data.ainfo.offset, tree->right->data.i, 4);
535 x86_mov_membase_imm (s->code, tree->left->data.ainfo.basereg,
536 tree->left->data.ainfo.offset, tree->right->data.i, 4);
539 x86_mov_memindex_imm (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
540 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
541 tree->right->data.i, 4);
544 x86_mov_memindex_imm (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
545 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
546 tree->right->data.i, 4);
551 stmt: STIND_I4 (addr, reg) {
553 switch (tree->left->data.ainfo.amode) {
556 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
560 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
561 tree->left->data.ainfo.offset, tree->right->reg1, 4);
564 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
565 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
566 tree->right->reg1, 4);
569 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
570 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
571 tree->right->reg1, 4);
576 stmt: REMOTE_STIND_I4 (reg, reg) {
579 int lreg = tree->left->reg1;
580 int rreg = tree->right->reg1;
589 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
590 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
591 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
593 /* this is a transparent proxy - remote the call */
595 /* save value to stack */
596 x86_push_reg (s->code, rreg);
598 x86_push_reg (s->code, X86_ESP);
599 x86_push_imm (s->code, tree->data.fi.field);
600 x86_push_imm (s->code, tree->data.fi.klass);
601 x86_push_reg (s->code, lreg);
602 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
603 x86_call_code (s->code, 0);
604 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
606 br [1] = s->code; x86_jump8 (s->code, 0);
608 x86_patch (br [0], s->code);
609 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
610 tree->data.fi.field->offset;
611 x86_mov_membase_reg (s->code, lreg, offset, rreg, 4);
613 x86_patch (br [1], s->code);
616 stmt: STIND_I1 (addr, reg) {
617 PRINT_REG ("STIND_I1", tree->right->reg1);
619 switch (tree->left->data.ainfo.amode) {
622 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 1);
626 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
627 tree->left->data.ainfo.offset, tree->right->reg1, 1);
630 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
631 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
632 tree->right->reg1, 1);
635 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
636 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
637 tree->right->reg1, 1);
642 stmt: REMOTE_STIND_I1 (reg, reg) {
645 int lreg = tree->left->reg1;
646 int rreg = tree->right->reg1;
655 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
656 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
657 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
659 /* this is a transparent proxy - remote the call */
661 /* save value to stack */
662 x86_push_reg (s->code, rreg);
664 x86_push_reg (s->code, X86_ESP);
665 x86_push_imm (s->code, tree->data.fi.field);
666 x86_push_imm (s->code, tree->data.fi.klass);
667 x86_push_reg (s->code, lreg);
668 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
669 x86_call_code (s->code, 0);
670 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
672 br [1] = s->code; x86_jump8 (s->code, 0);
674 x86_patch (br [0], s->code);
675 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
676 tree->data.fi.field->offset;
677 x86_mov_membase_reg (s->code, lreg, offset, rreg, 1);
679 x86_patch (br [1], s->code);
682 stmt: STIND_I2 (addr, reg) {
683 PRINT_REG ("STIND_I2", tree->right->reg1);
685 switch (tree->left->data.ainfo.amode) {
688 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 2);
692 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
693 tree->left->data.ainfo.offset, tree->right->reg1, 2);
696 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
697 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
698 tree->right->reg1, 2);
701 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
702 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
703 tree->right->reg1, 2);
708 stmt: REMOTE_STIND_I2 (reg, reg) {
711 int lreg = tree->left->reg1;
712 int rreg = tree->right->reg1;
721 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
722 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
723 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
725 /* this is a transparent proxy - remote the call */
727 /* save value to stack */
728 x86_push_reg (s->code, rreg);
730 x86_push_reg (s->code, X86_ESP);
731 x86_push_imm (s->code, tree->data.fi.field);
732 x86_push_imm (s->code, tree->data.fi.klass);
733 x86_push_reg (s->code, lreg);
734 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
735 x86_call_code (s->code, 0);
736 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
738 br [1] = s->code; x86_jump8 (s->code, 0);
740 x86_patch (br [0], s->code);
741 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
742 tree->data.fi.field->offset;
743 x86_mov_membase_reg (s->code, lreg, offset, rreg, 2);
745 x86_patch (br [1], s->code);
748 reg: LDIND_I4 (ADDR_L) {
749 int treg = VARINFO (s, tree->left->data.i).reg;
751 if (treg != tree->reg1)
752 x86_mov_reg_reg (s->code, tree->reg1, treg, 4);
755 MBCOND ((VARINFO (data, tree->left->data.i).reg >= 0));
759 stmt: STIND_I4 (ADDR_L, CONST_I4) {
760 int treg = VARINFO (s, tree->left->data.i).reg;
762 x86_mov_reg_imm (s->code, treg, tree->right->data.i);
765 MBCOND ((VARINFO (data, tree->left->data.i).reg >= 0));
769 stmt: STIND_I4 (ADDR_L, LDIND_I4 (ADDR_L)) {
770 int treg = VARINFO (s, tree->left->data.i).reg;
771 int offset = VARINFO (s, tree->right->left->data.i).offset;
773 x86_mov_reg_membase (s->code, treg, X86_EBP, offset, 4);
775 MBCOND ((VARINFO (data, tree->left->data.i).reg >= 0));
776 MBCOND ((VARINFO (data, tree->right->left->data.i).reg < 0));
780 stmt: STIND_I4 (ADDR_L, reg) {
781 int treg = VARINFO (s, tree->left->data.i).reg;
783 if (treg != tree->right->reg1)
784 x86_mov_reg_reg (s->code, treg, tree->right->reg1, 4);
787 MBCOND ((VARINFO (data, tree->left->data.i).reg >= 0));
792 reg: LDIND_I4 (addr) {
794 switch (tree->left->data.ainfo.amode) {
797 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
801 x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
802 tree->left->data.ainfo.offset, 4);
805 x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
806 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
809 x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
810 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
811 tree->left->data.ainfo.shift, 4);
816 PRINT_REG ("LDIND_I4", tree->reg1);
819 reg: LDIND_I1 (addr) {
820 switch (tree->left->data.ainfo.amode) {
823 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, FALSE);
827 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
828 tree->left->data.ainfo.offset, TRUE, FALSE);
831 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
832 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, TRUE, FALSE);
835 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
836 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
837 tree->left->data.ainfo.shift, TRUE, FALSE);
841 PRINT_REG ("LDIND_I1", tree->reg1);
844 reg: LDIND_U1 (addr) {
845 switch (tree->left->data.ainfo.amode) {
848 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, FALSE);
852 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
853 tree->left->data.ainfo.offset, FALSE, FALSE);
856 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
857 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, FALSE, FALSE);
860 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
861 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
862 tree->left->data.ainfo.shift, FALSE, FALSE);
866 PRINT_REG ("LDIND_U1", tree->reg1);
869 reg: LDIND_I2 (addr) {
870 switch (tree->left->data.ainfo.amode) {
873 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, TRUE, TRUE);
877 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
878 tree->left->data.ainfo.offset, TRUE, TRUE);
881 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
882 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, TRUE, TRUE);
885 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
886 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
887 tree->left->data.ainfo.shift, TRUE, TRUE);
891 PRINT_REG ("LDIND_U2", tree->reg1);
894 reg: LDIND_U2 (addr) {
895 switch (tree->left->data.ainfo.amode) {
898 x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, FALSE, TRUE);
902 x86_widen_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg,
903 tree->left->data.ainfo.offset, FALSE, TRUE);
906 x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
907 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, FALSE, TRUE);
910 x86_widen_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg,
911 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
912 tree->left->data.ainfo.shift, FALSE, TRUE);
916 PRINT_REG ("LDIND_U2", tree->reg1);
919 reg: REMOTE_LDFLDA (reg) {
922 int lreg = tree->left->reg1;
927 if (tree->reg1 != treg)
928 x86_push_reg (s->code, treg);
930 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
931 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
932 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
934 /* this is a transparent proxy - remote the call */
936 x86_push_reg (s->code, X86_EAX);
938 x86_push_reg (s->code, X86_EDX);
939 x86_push_reg (s->code, X86_ECX);
941 x86_push_imm (s->code, 0);
942 x86_push_imm (s->code, tree->data.fi.field);
943 x86_push_imm (s->code, tree->data.fi.klass);
944 x86_push_reg (s->code, lreg);
945 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_load_remote_field);
946 x86_call_code (s->code, 0);
947 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
950 x86_mov_reg_reg (s->code, treg, X86_EAX, 4);
952 x86_pop_reg (s->code, X86_ECX);
954 x86_pop_reg (s->code, X86_EDX);
956 x86_pop_reg (s->code, X86_EAX);
958 x86_mov_reg_reg (s->code, tree->reg1, treg, 4);
960 br [1] = s->code; x86_jump8 (s->code, 0);
962 x86_patch (br [0], s->code);
963 if (tree->data.fi.klass->valuetype)
964 x86_lea_membase (s->code, tree->reg1, lreg,
965 tree->data.fi.field->offset - sizeof (MonoObject));
967 x86_lea_membase (s->code, tree->reg1, lreg, tree->data.fi.field->offset);
969 x86_patch (br [1], s->code);
971 if (tree->reg1 != treg)
972 x86_pop_reg (s->code, treg);
976 int offset = VARINFO (s, tree->data.i).offset;
978 x86_lea_membase (s->code, tree->reg1, X86_EBP, offset);
980 PRINT_REG ("ADDR_L", tree->reg1);
982 MBCOND (VARINFO (data, tree->data.i).reg < 0);
988 x86_mov_reg_imm (s->code, tree->reg1, tree->data.p);
992 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
996 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
1000 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
1003 reg: CONV_U2 (reg) {
1004 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
1008 x86_mov_reg_imm (s->code, tree->reg1, tree->data.i);
1011 reg: CONV_I4 (reg) {
1012 if (tree->reg1 != tree->left->reg1)
1013 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1014 PRINT_REG ("CONV_I4", tree->left->reg1);
1017 reg: CONV_U4 (reg) {
1018 if (tree->reg1 != tree->left->reg1)
1019 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1020 PRINT_REG ("CONV_U4", tree->left->reg1);
1023 reg: CONV_OVF_I4 (reg) {
1024 if (tree->reg1 != tree->left->reg1)
1025 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1026 PRINT_REG ("CONV_OVF_I4", tree->left->reg1);
1029 reg: CONV_OVF_U4 (reg) {
1030 /* Keep in sync with CONV_OVF_I4_UN below, they are the same on 32-bit machines */
1031 x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
1032 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1033 if (tree->reg1 != tree->left->reg1)
1034 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1037 reg: CONV_OVF_I4_UN (reg) {
1038 /* Keep in sync with CONV_OVF_U4 above, they are the same on 32-bit machines */
1039 x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
1040 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1041 if (tree->reg1 != tree->left->reg1)
1042 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1045 reg: CONV_OVF_I1 (reg) {
1046 /* probe value to be within -128 to 127 */
1047 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 127);
1048 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, TRUE, "OverflowException");
1049 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, -128);
1050 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GT, TRUE, "OverflowException");
1051 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
1054 reg: CONV_OVF_I1_UN (reg) {
1055 /* probe values between 0 to 128 */
1056 x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff80);
1057 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1058 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
1061 reg: CONV_OVF_U1 (reg) {
1062 /* Keep in sync with CONV_OVF_U1_UN routine below, they are the same on 32-bit machines */
1063 /* probe value to be within 0 to 255 */
1064 x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff00);
1065 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1066 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
1069 reg: CONV_OVF_U1_UN (reg) {
1070 /* Keep in sync with CONV_OVF_U1 routine above, they are the same on 32-bit machines */
1071 /* probe value to be within 0 to 255 */
1072 x86_test_reg_imm (s->code, tree->left->reg1, 0xffffff00);
1073 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1074 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
1077 reg: CONV_OVF_I2 (reg) {
1078 /* Probe value to be within -32768 and 32767 */
1079 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 32767);
1080 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, TRUE, "OverflowException");
1081 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, -32768);
1082 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GE, TRUE, "OverflowException");
1083 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
1086 reg: CONV_OVF_U2 (reg) {
1087 /* Keep in sync with CONV_OVF_U2_UN below, they are the same on 32-bit machines */
1088 /* Probe value to be within 0 and 65535 */
1089 x86_test_reg_imm (s->code, tree->left->reg1, 0xffff0000);
1090 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
1091 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
1094 reg: CONV_OVF_U2_UN (reg) {
1095 /* Keep in sync with CONV_OVF_U2 above, they are the same on 32-bit machines */
1096 /* Probe value to be within 0 and 65535 */
1097 x86_test_reg_imm (s->code, tree->left->reg1, 0xffff0000);
1098 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1099 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
1102 reg: CONV_OVF_I2_UN (reg) {
1103 /* Convert uint value into short, value within 0 and 32767 */
1104 x86_test_reg_imm (s->code, tree->left->reg1, 0xffff8000);
1105 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
1106 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
1109 reg: MUL (reg, CONST_I4) "MB_USE_OPT1(0)" {
1110 unsigned int i, j, k, v;
1112 v = tree->right->data.i;
1113 for (i = 0, j = 1, k = 0xfffffffe; i < 32; i++, j = j << 1, k = k << 1) {
1118 if (v < 0 || i == 32 || v & k) {
1121 /* LEA r1, [r2 + r2*2] */
1122 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 1);
1125 /* LEA r1, [r2 + r2*4] */
1126 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 2);
1129 /* LEA r1, [r2 + r2*2] */
1131 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 1);
1132 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->reg1);
1135 /* LEA r1, [r2 + r2*8] */
1136 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 3);
1139 /* LEA r1, [r2 + r2*4] */
1141 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 2);
1142 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->reg1);
1145 /* LEA r1, [r2 + r2*2] */
1147 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 1);
1148 x86_shift_reg_imm (s->code, X86_SHL, tree->reg1, 2);
1151 /* LEA r1, [r2 + r2*4] */
1152 /* LEA r1, [r1 + r1*4] */
1153 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 2);
1154 x86_lea_memindex (s->code, tree->reg1, tree->reg1, 0, tree->reg1, 2);
1157 /* LEA r1, [r2 + r2*4] */
1159 /* LEA r1, [r1 + r1*4] */
1160 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1, 0, tree->left->reg1, 2);
1161 x86_shift_reg_imm (s->code, X86_SHL, tree->reg1, 2);
1162 x86_lea_memindex (s->code, tree->reg1, tree->reg1, 0, tree->reg1, 2);
1165 x86_imul_reg_reg_imm (s->code, tree->reg1, tree->left->reg1, tree->right->data.i);
1169 x86_shift_reg_imm (s->code, X86_SHL, tree->left->reg1, i);
1170 if (tree->reg1 != tree->left->reg1)
1171 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1175 reg: MUL (reg, reg) {
1176 x86_imul_reg_reg (s->code, tree->left->reg1, tree->right->reg1);
1178 if (tree->reg1 != tree->left->reg1)
1179 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1182 reg: MUL_OVF (reg, reg) {
1183 x86_imul_reg_reg (s->code, tree->left->reg1, tree->right->reg1);
1184 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
1186 if (tree->reg1 != tree->left->reg1)
1187 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1190 reg: MUL_OVF_UN (reg, reg) {
1191 mono_assert (tree->right->reg1 != X86_EAX);
1193 if (tree->left->reg1 != X86_EAX)
1194 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1196 x86_mul_reg (s->code, tree->right->reg1, FALSE);
1197 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
1199 mono_assert (tree->reg1 == X86_EAX &&
1200 tree->reg2 == X86_EDX);
1203 reg: DIV (reg, CONST_I4) {
1204 unsigned int i, j, k, v;
1206 v = tree->right->data.i;
1207 for (i = 0, j = 1, k = 0xfffffffe; i < 32; i++, j = j << 1, k = k << 1) {
1212 x86_shift_reg_imm (s->code, X86_SAR, tree->left->reg1, i);
1213 if (tree->reg1 != tree->left->reg1)
1214 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1217 unsigned int i, j, k, v;
1222 v = tree->right->data.i;
1223 for (i = 0, j = 1, k = 0xfffffffe; i < 32; i++, j = j << 1, k = k << 1) {
1228 if (i == 32 || v & k)
1235 reg: DIV (reg, reg) {
1236 mono_assert (tree->right->reg1 != X86_EAX);
1238 if (tree->left->reg1 != X86_EAX)
1239 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1242 x86_div_reg (s->code, tree->right->reg1, TRUE);
1244 mono_assert (tree->reg1 == X86_EAX &&
1245 tree->reg2 == X86_EDX);
1248 reg: DIV_UN (reg, CONST_I4) {
1249 unsigned int i, j, k, v;
1252 v = tree->right->data.i;
1253 for (i = 0, j = 1, k = 0xfffffffe; i < 32; i++, j = j << 1, k = k << 1) {
1258 if (i == 32 || v & k) {
1259 for (i = 32, j = 0x80000000; --i >= 0; j >>= 1) {
1263 /* k = 32 + number of significant bits in v - 1 */
1267 for (i = 0; i < k; i++) f *= 2.0f;
1273 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg1, k - 32);
1274 if (tree->reg1 != tree->left->reg1)
1275 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1276 } else if (r < 0.5f) {
1277 if (tree->left->reg1 != X86_EAX)
1278 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1279 x86_mov_reg_imm (s->code, X86_EDX, (guint32) floor(f));
1280 /* x86_inc_reg (s->code, X86_EAX); */
1281 /* INC is faster but we have to check for overflow. */
1282 x86_alu_reg_imm (s->code, X86_ADD, X86_EAX, 1);
1283 x86_branch8(s->code, X86_CC_C, 2, FALSE);
1284 x86_mul_reg (s->code, X86_EDX, FALSE);
1285 x86_shift_reg_imm (s->code, X86_SHR, X86_EDX, k - 32);
1286 if (tree->reg1 != X86_EDX)
1287 x86_mov_reg_reg (s->code, tree->reg1, X86_EDX, 4);
1289 if (tree->left->reg1 != X86_EAX)
1290 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1291 x86_mov_reg_imm (s->code, X86_EDX, (guint32) ceil(f));
1292 x86_mul_reg (s->code, X86_EDX, FALSE);
1293 x86_shift_reg_imm (s->code, X86_SHR, X86_EDX, k - 32);
1294 if (tree->reg1 != X86_EDX)
1295 x86_mov_reg_reg (s->code, tree->reg1, X86_EDX, 4);
1298 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg1, i);
1299 if (tree->reg1 != tree->left->reg1)
1300 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1305 reg: DIV_UN (reg, reg) {
1306 mono_assert (tree->right->reg1 != X86_EAX);
1308 if (tree->left->reg1 != X86_EAX)
1309 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1311 x86_mov_reg_imm (s->code, X86_EDX, 0);
1312 x86_div_reg (s->code, tree->right->reg1, FALSE);
1314 mono_assert (tree->reg1 == X86_EAX &&
1315 tree->reg2 == X86_EDX);
1318 reg: REM (reg, reg) {
1319 mono_assert (tree->right->reg1 != X86_EAX);
1320 mono_assert (tree->right->reg1 != X86_EDX);
1322 if (tree->left->reg1 != X86_EAX)
1323 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1325 /* sign extend to 64bit in EAX/EDX */
1327 x86_div_reg (s->code, tree->right->reg1, TRUE);
1328 x86_mov_reg_reg (s->code, X86_EAX, X86_EDX, 4);
1330 mono_assert (tree->reg1 == X86_EAX &&
1331 tree->reg2 == X86_EDX);
1334 reg: REM_UN (reg, reg) {
1335 mono_assert (tree->right->reg1 != X86_EAX);
1336 mono_assert (tree->right->reg1 != X86_EDX);
1338 if (tree->left->reg1 != X86_EAX)
1339 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
1341 /* zero extend to 64bit in EAX/EDX */
1342 x86_mov_reg_imm (s->code, X86_EDX, 0);
1343 x86_div_reg (s->code, tree->right->reg1, FALSE);
1344 x86_mov_reg_reg (s->code, X86_EAX, X86_EDX, 4);
1346 mono_assert (tree->reg1 == X86_EAX &&
1347 tree->reg2 == X86_EDX);
1350 reg: ADD (reg, CONST_I4) "MB_USE_OPT1(0)" {
1351 if (tree->right->data.i == 1)
1352 x86_inc_reg (s->code, tree->left->reg1);
1354 x86_alu_reg_imm (s->code, X86_ADD, tree->left->reg1, tree->right->data.i);
1356 if (tree->reg1 != tree->left->reg1)
1357 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1361 reg: ADD (reg, LDIND_I4 (ADDR_L)) {
1362 int treg = VARINFO (s, tree->right->left->data.i).reg;
1364 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, treg);
1366 if (tree->reg1 != tree->left->reg1)
1367 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1369 MBCOND ((VARINFO (data, tree->right->left->data.i).reg >= 0));
1373 reg: ADD (reg, reg) {
1374 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
1376 if (tree->reg1 != tree->left->reg1)
1377 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1380 reg: ADD_OVF (reg, reg) {
1381 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
1382 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
1384 if (tree->reg1 != tree->left->reg1)
1385 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1388 reg: ADD_OVF_UN (reg, reg) {
1389 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
1390 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
1392 if (tree->reg1 != tree->left->reg1)
1393 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1396 reg: SUB (reg, CONST_I4) "MB_USE_OPT1(0)" {
1397 if (tree->right->data.i == 1)
1398 x86_dec_reg (s->code, tree->left->reg1);
1400 x86_alu_reg_imm (s->code, X86_SUB, tree->left->reg1, tree->right->data.i);
1402 if (tree->reg1 != tree->left->reg1)
1403 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1406 reg: SUB (reg, LDIND_I4 (ADDR_L)) {
1407 int treg = VARINFO (s, tree->right->left->data.i).reg;
1409 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, treg);
1411 if (tree->reg1 != tree->left->reg1)
1412 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1414 MBCOND ((VARINFO (data, tree->right->left->data.i).reg >= 0));
1418 reg: SUB (reg, reg) {
1419 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
1421 if (tree->reg1 != tree->left->reg1)
1422 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1425 reg: SUB_OVF (reg, reg) {
1426 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
1427 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
1429 if (tree->reg1 != tree->left->reg1)
1430 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1433 reg: SUB_OVF_UN (reg, reg) {
1434 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
1435 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
1437 if (tree->reg1 != tree->left->reg1)
1438 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1441 reg: CSET (cflags) {
1443 switch (tree->data.i) {
1445 x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
1448 x86_set_reg (s->code, X86_CC_GT, tree->reg1, TRUE);
1451 x86_set_reg (s->code, X86_CC_GT, tree->reg1, FALSE);
1454 x86_set_reg (s->code, X86_CC_LT, tree->reg1, TRUE);
1457 x86_set_reg (s->code, X86_CC_LT, tree->reg1, FALSE);
1460 g_assert_not_reached ();
1463 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
1466 reg: AND (reg, CONST_I4) "MB_USE_OPT1(0)" {
1467 x86_alu_reg_imm (s->code, X86_AND, tree->left->reg1, tree->right->data.i);
1469 if (tree->reg1 != tree->left->reg1)
1470 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1473 reg: AND (reg, reg) {
1474 x86_alu_reg_reg (s->code, X86_AND, tree->left->reg1, tree->right->reg1);
1476 if (tree->reg1 != tree->left->reg1)
1477 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1480 reg: OR (reg, CONST_I4) "MB_USE_OPT1(0)" {
1481 x86_alu_reg_imm (s->code, X86_OR, tree->left->reg1, tree->right->data.i);
1483 if (tree->reg1 != tree->left->reg1)
1484 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1487 reg: OR (reg, reg) {
1488 x86_alu_reg_reg (s->code, X86_OR, tree->left->reg1, tree->right->reg1);
1490 if (tree->reg1 != tree->left->reg1)
1491 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1494 reg: XOR (reg, CONST_I4) "MB_USE_OPT1(0)" {
1495 x86_alu_reg_imm (s->code, X86_XOR, tree->left->reg1, tree->right->data.i);
1497 if (tree->reg1 != tree->left->reg1)
1498 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1501 reg: XOR (reg, reg) {
1502 x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->right->reg1);
1504 if (tree->reg1 != tree->left->reg1)
1505 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1509 x86_neg_reg (s->code, tree->left->reg1);
1511 if (tree->reg1 != tree->left->reg1)
1512 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1516 x86_not_reg (s->code, tree->left->reg1);
1518 if (tree->reg1 != tree->left->reg1)
1519 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1522 reg: SHL (reg, CONST_I4) {
1523 x86_shift_reg_imm (s->code, X86_SHL, tree->left->reg1, tree->right->data.i);
1525 if (tree->reg1 != tree->left->reg1)
1526 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1529 reg: SHL (reg, reg) {
1530 if (tree->right->reg1 != X86_ECX) {
1531 x86_push_reg (s->code, X86_ECX);
1532 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1534 x86_shift_reg (s->code, X86_SHL, tree->left->reg1);
1536 if (tree->reg1 != tree->left->reg1)
1537 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1539 if (tree->right->reg1 != X86_ECX)
1540 x86_pop_reg (s->code, X86_ECX);
1542 mono_assert (tree->reg1 != X86_ECX &&
1543 tree->left->reg1 != X86_ECX);
1546 reg: SHR (reg, CONST_I4) {
1547 x86_shift_reg_imm (s->code, X86_SAR, tree->left->reg1, tree->right->data.i);
1549 if (tree->reg1 != tree->left->reg1)
1550 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1553 reg: SHR (reg, reg) {
1554 if (tree->right->reg1 != X86_ECX) {
1555 x86_push_reg (s->code, X86_ECX);
1556 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1559 x86_shift_reg (s->code, X86_SAR, tree->left->reg1);
1561 if (tree->reg1 != tree->left->reg1)
1562 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1564 if (tree->right->reg1 != X86_ECX)
1565 x86_pop_reg (s->code, X86_ECX);
1567 mono_assert (tree->reg1 != X86_ECX &&
1568 tree->left->reg1 != X86_ECX);
1571 reg: SHR_UN (reg, CONST_I4) {
1572 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg1, tree->right->data.i);
1574 if (tree->reg1 != tree->left->reg1)
1575 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1578 reg: SHR_UN (reg, reg) {
1579 if (tree->right->reg1 != X86_ECX) {
1580 x86_push_reg (s->code, X86_ECX);
1581 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
1584 x86_shift_reg (s->code, X86_SHR, tree->left->reg1);
1586 if (tree->reg1 != tree->left->reg1)
1587 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1589 if (tree->right->reg1 != X86_ECX)
1590 x86_pop_reg (s->code, X86_ECX);
1592 mono_assert (tree->reg1 != X86_ECX &&
1593 tree->left->reg1 != X86_ECX);
1596 reg: LDSFLDA (CONST_I4) {
1597 if (tree->reg1 != X86_EAX)
1598 x86_push_reg (s->code, X86_EAX);
1599 x86_push_reg (s->code, X86_ECX);
1600 x86_push_reg (s->code, X86_EDX);
1602 x86_push_imm (s->code, tree->left->data.i);
1603 x86_push_imm (s->code, tree->data.klass);
1604 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_ldsflda);
1605 x86_call_code (s->code, 0);
1606 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1608 x86_pop_reg (s->code, X86_EDX);
1609 x86_pop_reg (s->code, X86_ECX);
1610 if (tree->reg1 != X86_EAX) {
1611 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1612 x86_pop_reg (s->code, X86_EAX);
1618 x86_mov_reg_membase (s->code, tree->reg1, tree->left->reg1,
1619 G_STRUCT_OFFSET (MonoArray, max_length), 4);
1622 reg: LDELEMA (reg, CONST_I4) {
1625 x86_alu_membase_imm (s->code, X86_CMP, tree->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length), tree->right->data.i);
1626 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GT, FALSE, "IndexOutOfRangeException");
1628 ind = tree->data.i * tree->right->data.i + G_STRUCT_OFFSET (MonoArray, vector);
1630 x86_alu_reg_imm (s->code, X86_ADD, tree->left->reg1, ind);
1632 if (tree->reg1 != tree->left->reg1)
1633 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1637 reg: LDELEMA (reg, reg) {
1639 x86_alu_reg_membase (s->code, X86_CMP, tree->right->reg1, tree->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length));
1640 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LT, FALSE, "IndexOutOfRangeException");
1642 if (tree->data.i == 1 || tree->data.i == 2 ||
1643 tree->data.i == 4 || tree->data.i == 8) {
1644 static int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
1645 x86_lea_memindex (s->code, tree->reg1, tree->left->reg1,
1646 G_STRUCT_OFFSET (MonoArray, vector), tree->right->reg1,
1647 fast_log2 [tree->data.i]);
1649 x86_imul_reg_reg_imm (s->code, tree->right->reg1, tree->right->reg1, tree->data.i);
1650 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
1651 x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, G_STRUCT_OFFSET (MonoArray, vector));
1656 if (tree->reg1 != X86_EAX)
1657 x86_push_reg (s->code, X86_EAX);
1658 x86_push_reg (s->code, X86_ECX);
1659 x86_push_reg (s->code, X86_EDX);
1661 x86_push_imm (s->code, tree->data.p);
1662 x86_push_imm (s->code, s->method->klass->image);
1663 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_ldstr_wrapper);
1664 x86_call_code (s->code, 0);
1665 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1667 x86_pop_reg (s->code, X86_EDX);
1668 x86_pop_reg (s->code, X86_ECX);
1669 if (tree->reg1 != X86_EAX) {
1670 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1671 x86_pop_reg (s->code, X86_EAX);
1674 PRINT_REG ("LDSTR", tree->reg1);
1678 if (tree->reg1 != X86_EAX)
1679 x86_push_reg (s->code, X86_EAX);
1680 x86_push_reg (s->code, X86_ECX);
1681 x86_push_reg (s->code, X86_EDX);
1683 x86_push_reg (s->code, tree->left->reg1);
1684 x86_push_imm (s->code, tree->data.p);
1685 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_array_new_wrapper);
1686 x86_call_code (s->code, 0);
1687 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1689 x86_pop_reg (s->code, X86_EDX);
1690 x86_pop_reg (s->code, X86_ECX);
1691 if (tree->reg1 != X86_EAX) {
1692 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1693 x86_pop_reg (s->code, X86_EAX);
1696 PRINT_REG ("NEWARR", tree->reg1);
1699 reg: NEWARR_SPEC (reg) {
1700 if (tree->reg1 != X86_EAX)
1701 x86_push_reg (s->code, X86_EAX);
1702 x86_push_reg (s->code, X86_ECX);
1703 x86_push_reg (s->code, X86_EDX);
1705 x86_push_reg (s->code, tree->left->reg1);
1706 x86_push_imm (s->code, tree->data.p);
1707 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_array_new_specific);
1708 x86_call_code (s->code, 0);
1709 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1711 x86_pop_reg (s->code, X86_EDX);
1712 x86_pop_reg (s->code, X86_ECX);
1713 if (tree->reg1 != X86_EAX) {
1714 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1715 x86_pop_reg (s->code, X86_EAX);
1718 PRINT_REG ("NEWARR_SPEC", tree->reg1);
1722 if (tree->reg1 != X86_EAX)
1723 x86_push_reg (s->code, X86_EAX);
1724 x86_push_reg (s->code, X86_ECX);
1725 x86_push_reg (s->code, X86_EDX);
1727 x86_push_imm (s->code, tree->data.klass);
1728 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_object_new_wrapper);
1729 x86_call_code (s->code, 0);
1730 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
1732 x86_pop_reg (s->code, X86_EDX);
1733 x86_pop_reg (s->code, X86_ECX);
1734 if (tree->reg1 != X86_EAX) {
1735 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1736 x86_pop_reg (s->code, X86_EAX);
1738 PRINT_REG ("NEWOBJ", tree->reg1);
1742 if (tree->reg1 != X86_EAX)
1743 x86_push_reg (s->code, X86_EAX);
1744 x86_push_reg (s->code, X86_ECX);
1745 x86_push_reg (s->code, X86_EDX);
1747 x86_push_imm (s->code, tree->data.p);
1748 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_object_new_specific);
1749 x86_call_code (s->code, 0);
1750 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
1752 x86_pop_reg (s->code, X86_EDX);
1753 x86_pop_reg (s->code, X86_ECX);
1754 if (tree->reg1 != X86_EAX) {
1755 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1756 x86_pop_reg (s->code, X86_EAX);
1758 PRINT_REG ("NEWOBJ_SPEC", tree->reg1);
1761 reg: OBJADDR (reg) {
1762 if (tree->left->reg1 != tree->reg1)
1763 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1766 reg: VTADDR (ADDR_L) {
1767 int offset = VARINFO (s, tree->left->data.i).offset;
1769 x86_lea_membase (s->code, tree->reg1, X86_EBP, offset);
1773 x86_push_reg (s->code, tree->left->reg1);
1774 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, g_free);
1775 x86_call_code (s->code, 0);
1776 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
1779 stmt: PROC2 (reg, reg) {
1780 x86_push_reg (s->code, tree->right->reg1);
1781 x86_push_reg (s->code, tree->left->reg1);
1782 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->data.p);
1783 x86_call_code (s->code, 0);
1784 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
1787 stmt: PROC3 (reg, CPSRC (reg, reg)) {
1788 x86_push_reg (s->code, tree->right->right->reg1);
1789 x86_push_reg (s->code, tree->right->left->reg1);
1790 x86_push_reg (s->code, tree->left->reg1);
1791 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->data.p);
1792 x86_call_code (s->code, 0);
1793 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
1797 if (tree->reg1 != X86_EAX)
1798 x86_push_reg (s->code, X86_EAX);
1799 x86_push_reg (s->code, X86_ECX);
1800 x86_push_reg (s->code, X86_EDX);
1802 x86_push_reg (s->code, tree->left->reg1);
1804 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->data.p);
1805 x86_call_code (s->code, 0);
1806 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
1808 x86_pop_reg (s->code, X86_EDX);
1809 x86_pop_reg (s->code, X86_ECX);
1810 if (tree->reg1 != X86_EAX) {
1811 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
1812 x86_pop_reg (s->code, X86_EAX);
1816 reg: LOCALLOC (CONST_I4) {
1820 size = (tree->left->data.i + (MONO_FRAME_ALIGNMENT - 1)) & ~(MONO_FRAME_ALIGNMENT - 1); // align to MONO_FRAME_ALIGNMENT boundary
1824 mono_emit_stack_alloc_const (s, tree, size);
1826 if (tree->reg1 != X86_EAX && tree->left->reg1 != X86_EAX) {
1827 x86_push_reg (s->code, X86_EAX);
1830 if (tree->reg1 != X86_ECX && tree->left->reg1 != X86_ECX) {
1831 x86_push_reg (s->code, X86_ECX);
1834 if (tree->reg1 != X86_EDI && tree->left->reg1 != X86_EDI) {
1835 x86_push_reg (s->code, X86_EDI);
1839 x86_mov_reg_imm (s->code, X86_ECX, size >> 2);
1840 x86_alu_reg_reg (s->code, X86_SUB, X86_EAX, X86_EAX);
1842 x86_lea_membase (s->code, X86_EDI, X86_ESP, offset);
1844 x86_prefix (s->code, X86_REP_PREFIX);
1845 x86_stosd (s->code);
1847 if (tree->reg1 != X86_ECX && tree->left->reg1 != X86_ECX)
1848 x86_pop_reg (s->code, X86_ECX);
1849 if (tree->reg1 != X86_EAX && tree->left->reg1 != X86_EAX)
1850 x86_pop_reg (s->code, X86_EAX);
1851 if (tree->reg1 != X86_EDI && tree->left->reg1 != X86_EDI)
1852 x86_pop_reg (s->code, X86_EDI);
1855 x86_mov_reg_reg (s->code, tree->reg1, X86_ESP, 4);
1860 reg: LOCALLOC (reg) {
1862 /* size must be aligned to MONO_FRAME_ALIGNMENT bytes */
1863 x86_alu_reg_imm (s->code, X86_ADD, tree->left->reg1, MONO_FRAME_ALIGNMENT - 1);
1864 x86_alu_reg_imm (s->code, X86_AND, tree->left->reg1, ~(MONO_FRAME_ALIGNMENT - 1));
1866 /* allocate space on stack */
1867 mono_emit_stack_alloc (s, tree);
1870 /* initialize with zero */
1871 if (tree->reg1 != X86_EAX && tree->left->reg1 != X86_EAX) {
1872 x86_push_reg (s->code, X86_EAX);
1875 if (tree->reg1 != X86_ECX && tree->left->reg1 != X86_ECX) {
1876 x86_push_reg (s->code, X86_ECX);
1879 if (tree->reg1 != X86_EDI && tree->left->reg1 != X86_EDI) {
1880 x86_push_reg (s->code, X86_EDI);
1884 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg1, 2);
1885 if (tree->left->reg1 != X86_ECX)
1886 x86_mov_reg_imm (s->code, X86_ECX, tree->left->reg1);
1887 x86_alu_reg_reg (s->code, X86_XOR, X86_EAX, X86_EAX);
1889 x86_lea_membase (s->code, X86_EDI, X86_ESP, offset);
1891 x86_prefix (s->code, X86_REP_PREFIX);
1892 x86_stosl (s->code);
1894 if (tree->reg1 != X86_EDI && tree->left->reg1 != X86_EDI)
1895 x86_pop_reg (s->code, X86_EDI);
1896 if (tree->reg1 != X86_ECX && tree->left->reg1 != X86_ECX)
1897 x86_pop_reg (s->code, X86_ECX);
1898 if (tree->reg1 != X86_EAX && tree->left->reg1 != X86_EAX)
1899 x86_pop_reg (s->code, X86_EAX);
1902 x86_mov_reg_reg (s->code, tree->reg1, X86_ESP, 4);
1906 if (tree->reg1 != tree->left->reg1)
1907 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
1909 x86_push_reg (s->code, tree->reg1);
1910 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, 0, 4);
1911 x86_mov_reg_membase (s->code, tree->reg1, tree->reg1, 0, 4);
1912 x86_alu_membase_imm (s->code, X86_CMP, tree->reg1,
1913 G_STRUCT_OFFSET (MonoClass, element_class), ((int)(tree->data.klass->element_class)));
1914 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "InvalidCastException");
1915 x86_pop_reg (s->code, tree->reg1);
1916 x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, sizeof (MonoObject));
1919 reg: CASTCLASS (reg) {
1920 MonoClass *klass = tree->data.klass;
1922 int lreg = tree->left->reg1;
1924 x86_push_reg (s->code, lreg);
1925 x86_test_reg_reg (s->code, lreg, lreg);
1926 br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
1928 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1929 /* lreg = obj->vtable */
1930 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1932 x86_alu_membase_imm (s->code, X86_CMP, lreg, G_STRUCT_OFFSET (MonoVTable, max_interface_id),
1933 klass->interface_id);
1934 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GE, FALSE, "InvalidCastException");
1935 /* lreg = obj->vtable->interface_offsets */
1936 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
1937 x86_alu_membase_imm (s->code, X86_CMP, lreg, klass->interface_id << 2, 0);
1938 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NE, FALSE, "InvalidCastException");
1941 /* lreg = obj->vtable */
1942 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1943 /* lreg = obj->vtable->klass */
1944 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1948 x86_alu_membase_imm (s->code, X86_CMP, lreg, G_STRUCT_OFFSET (MonoClass, rank), klass->rank);
1949 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "InvalidCastException");
1950 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, element_class), 4);
1951 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, baseval), 4);
1952 x86_alu_reg_mem (s->code, X86_SUB, lreg, &klass->element_class->baseval);
1953 x86_alu_reg_mem (s->code, X86_CMP, lreg, &klass->element_class->diffval);
1954 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, FALSE, "InvalidCastException");
1958 if (klass->marshalbyref) {
1959 /* check for transparent_proxy */
1960 x86_alu_reg_imm (s->code, X86_CMP, lreg, (int)mono_defaults.transparent_proxy_class);
1961 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
1964 x86_mov_reg_membase (s->code, lreg, X86_ESP, 0, 4);
1965 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoTransparentProxy,
1968 x86_patch (br [1], s->code);
1971 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, baseval), 4);
1972 x86_alu_reg_mem (s->code, X86_SUB, lreg, &klass->baseval);
1973 x86_alu_reg_mem (s->code, X86_CMP, lreg, &klass->diffval);
1974 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LE, FALSE, "InvalidCastException");
1978 x86_patch (br [0], s->code);
1979 x86_pop_reg (s->code, tree->reg1);
1983 MonoClass *klass = tree->data.klass;
1985 int lreg = tree->left->reg1;
1987 x86_push_reg (s->code, lreg);
1988 x86_test_reg_reg (s->code, lreg, lreg);
1989 br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
1991 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1992 /* lreg = obj->vtable */
1993 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
1995 x86_alu_membase_imm (s->code, X86_CMP, lreg, G_STRUCT_OFFSET (MonoVTable, max_interface_id),
1996 klass->interface_id);
1997 br [1] = s->code; x86_branch8 (s->code, X86_CC_LT, 0, FALSE);
1998 /* lreg = obj->vtable->interface_offsets */
1999 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
2000 x86_alu_membase_imm (s->code, X86_CMP, lreg, klass->interface_id << 2, 0);
2001 br [2] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
2002 x86_patch (br [1], s->code);
2003 x86_mov_membase_imm (s->code, X86_ESP, 0, 0, 4);
2004 x86_patch (br [2], s->code);
2008 /* lreg = obj->vtable */
2009 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2010 /* lreg = obj->vtable->klass */
2011 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2015 x86_alu_membase_imm (s->code, X86_CMP, lreg, G_STRUCT_OFFSET (MonoClass, rank), klass->rank);
2016 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
2017 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, element_class), 4);
2018 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, baseval), 4);
2019 x86_alu_reg_mem (s->code, X86_SUB, lreg, &klass->element_class->baseval);
2020 x86_alu_reg_mem (s->code, X86_CMP, lreg, &klass->element_class->diffval);
2021 br [2] = s->code; x86_branch8 (s->code, X86_CC_LE, 0, FALSE);
2022 x86_patch (br [1], s->code);
2023 x86_mov_membase_imm (s->code, X86_ESP, 0, 0, 4);
2024 x86_patch (br [2], s->code);
2028 if (klass->marshalbyref) {
2029 /* check for transparent_proxy */
2030 x86_alu_reg_imm (s->code, X86_CMP, lreg, (int)mono_defaults.transparent_proxy_class);
2031 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
2034 x86_mov_reg_membase (s->code, lreg, X86_ESP, 0, 4);
2035 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoTransparentProxy,
2037 x86_patch (br [1], s->code);
2040 x86_mov_reg_membase (s->code, lreg, lreg, G_STRUCT_OFFSET (MonoClass, baseval), 4);
2041 x86_alu_reg_mem (s->code, X86_SUB, lreg, &klass->baseval);
2042 x86_alu_reg_mem (s->code, X86_CMP, lreg, &klass->diffval);
2043 br [2] = s->code; x86_branch8 (s->code, X86_CC_LE, 0, FALSE);
2044 x86_mov_membase_imm (s->code, X86_ESP, 0, 0, 4);
2045 x86_patch (br [2], s->code);
2049 x86_patch (br [0], s->code);
2050 x86_pop_reg (s->code, tree->reg1);
2053 stmt: INITOBJ (reg) {
2056 if (!(i = tree->data.i))
2059 if (i == 1 || i == 2 || i == 4) {
2060 x86_mov_membase_imm (s->code, tree->left->reg1, 0, 0, i);
2064 i = tree->data.i / 4;
2065 j = tree->data.i % 4;
2067 if (tree->left->reg1 != X86_EDI) {
2068 x86_push_reg (s->code, X86_EDI);
2069 x86_mov_reg_reg (s->code, X86_EDI, tree->left->reg1, 4);
2073 x86_alu_reg_reg (s->code, X86_XOR, X86_EAX, X86_EAX);
2074 x86_mov_reg_imm (s->code, X86_ECX, i);
2076 x86_prefix (s->code, X86_REP_PREFIX);
2077 x86_stosl (s->code);
2079 for (i = 0; i < j; i++)
2080 x86_stosb (s->code);
2084 x86_mov_membase_imm (s->code, X86_EDI, 0, 0, 2);
2085 x86_mov_membase_imm (s->code, X86_EDI, 2, 0, 1);
2090 if (tree->left->reg1 != X86_EDI)
2091 x86_pop_reg (s->code, X86_EDI);
2094 stmt: CPBLK (reg, CPSRC (reg, CONST_I4)) {
2095 int dest_reg = tree->left->reg1;
2096 int source_reg = tree->right->left->reg1;
2097 int count = tree->right->right->data.i;
2098 int sreg = dest_reg != X86_EAX ? X86_EAX : X86_EDX;
2099 int spill_pos = 0, dest_offset = 0, source_offset = 0;
2100 int save_esi = FALSE, save_edi = FALSE;
2102 // TODO: handle unaligned. prefix
2108 x86_mov_reg_membase (s->code, sreg, source_reg, 0, 1);
2109 x86_mov_membase_reg (s->code, dest_reg, 0, sreg, 1);
2112 x86_mov_reg_membase (s->code, sreg, source_reg, 0, 2);
2113 x86_mov_membase_reg (s->code, dest_reg, 0, sreg, 2);
2116 x86_mov_reg_membase (s->code, sreg, source_reg, 0, 2);
2117 x86_mov_membase_reg (s->code, dest_reg, 0, sreg, 2);
2118 x86_mov_reg_membase (s->code, sreg, source_reg, 2, 1);
2119 x86_mov_membase_reg (s->code, dest_reg, 2, sreg, 1);
2122 x86_mov_reg_membase (s->code, sreg, source_reg, 0, 4);
2123 x86_mov_membase_reg (s->code, dest_reg, 0, sreg, 4);
2126 x86_mov_reg_membase (s->code, sreg, source_reg, 0, 4);
2127 x86_mov_membase_reg (s->code, dest_reg, 0, sreg, 4);
2128 x86_mov_reg_membase (s->code, sreg, source_reg, 4, 1);
2129 x86_mov_membase_reg (s->code, dest_reg, 4, sreg, 1);
2132 x86_mov_reg_membase (s->code, sreg, source_reg, 0, 4);
2133 x86_mov_membase_reg (s->code, dest_reg, 0, sreg, 4);
2134 x86_mov_reg_membase (s->code, sreg, source_reg, 4, 2);
2135 x86_mov_membase_reg (s->code, dest_reg, 4, sreg, 2);
2138 x86_mov_reg_membase (s->code, sreg, source_reg, 0, 4);
2139 x86_mov_membase_reg (s->code, dest_reg, 0, sreg, 4);
2140 x86_mov_reg_membase (s->code, sreg, source_reg, 4, 2);
2141 x86_mov_membase_reg (s->code, dest_reg, 4, sreg, 2);
2142 x86_mov_reg_membase (s->code, sreg, source_reg, 6, 1);
2143 x86_mov_membase_reg (s->code, dest_reg, 6, sreg, 1);
2146 x86_fild_membase (s->code, source_reg, 0, TRUE);
2147 x86_fist_pop_membase (s->code, dest_reg, 0, TRUE);
2150 x86_fild_membase (s->code, source_reg, 0, TRUE);
2151 x86_fist_pop_membase (s->code, dest_reg, 0, TRUE);
2152 x86_mov_reg_membase (s->code, sreg, source_reg, 8, 1);
2153 x86_mov_membase_reg (s->code, dest_reg, 8, sreg, 1);
2156 x86_fild_membase (s->code, source_reg, 0, TRUE);
2157 x86_fist_pop_membase (s->code, dest_reg, 0, TRUE);
2158 x86_mov_reg_membase (s->code, sreg, source_reg, 8, 2);
2159 x86_mov_membase_reg (s->code, dest_reg, 8, sreg, 2);
2162 x86_fild_membase (s->code, source_reg, 0, TRUE);
2163 x86_fist_pop_membase (s->code, dest_reg, 0, TRUE);
2164 x86_mov_reg_membase (s->code, sreg, source_reg, 8, 2);
2165 x86_mov_membase_reg (s->code, dest_reg, 8, sreg, 2);
2166 x86_mov_reg_membase (s->code, sreg, source_reg, 10, 1);
2167 x86_mov_membase_reg (s->code, dest_reg, 10, sreg, 1);
2170 x86_fild_membase (s->code, source_reg, 0, TRUE);
2171 x86_fist_pop_membase (s->code, dest_reg, 0, TRUE);
2172 x86_mov_reg_membase (s->code, sreg, source_reg, 8, 4);
2173 x86_mov_membase_reg (s->code, dest_reg, 8, sreg, 4);
2176 x86_fild_membase (s->code, source_reg, 0, TRUE);
2177 x86_fist_pop_membase (s->code, dest_reg, 0, TRUE);
2178 x86_mov_reg_membase (s->code, sreg, source_reg, 8, 4);
2179 x86_mov_membase_reg (s->code, dest_reg, 8, sreg, 4);
2180 x86_mov_reg_membase (s->code, sreg, source_reg, 12, 1);
2181 x86_mov_membase_reg (s->code, dest_reg, 12, sreg, 1);
2184 x86_fild_membase (s->code, source_reg, 0, TRUE);
2185 x86_fist_pop_membase (s->code, dest_reg, 0, TRUE);
2186 x86_mov_reg_membase (s->code, sreg, source_reg, 8, 4);
2187 x86_mov_membase_reg (s->code, dest_reg, 8, sreg, 4);
2188 x86_mov_reg_membase (s->code, sreg, source_reg, 12, 2);
2189 x86_mov_membase_reg (s->code, dest_reg, 12, sreg, 2);
2192 x86_fild_membase (s->code, source_reg, 0, TRUE);
2193 x86_fist_pop_membase (s->code, dest_reg, 0, TRUE);
2194 x86_mov_reg_membase (s->code, sreg, source_reg, 8, 4);
2195 x86_mov_membase_reg (s->code, dest_reg, 8, sreg, 4);
2196 x86_mov_reg_membase (s->code, sreg, source_reg, 12, 2);
2197 x86_mov_membase_reg (s->code, dest_reg, 12, sreg, 2);
2198 x86_mov_reg_membase (s->code, sreg, source_reg, 14, 1);
2199 x86_mov_membase_reg (s->code, dest_reg, 14, sreg, 1);
2202 g_assert (count > 15);
2204 if (dest_reg != X86_ESI && source_reg != X86_ESI &&
2205 mono_regset_reg_used (s->rs, X86_ESI))
2207 if (dest_reg != X86_EDI && source_reg != X86_EDI &&
2208 mono_regset_reg_used (s->rs, X86_EDI))
2212 x86_push_reg (s->code, X86_ESI);
2214 x86_push_reg (s->code, X86_EDI);
2216 if (dest_reg == X86_ESI) {
2217 dest_offset = ++spill_pos;
2219 if (source_reg == X86_EDI) {
2220 source_offset = ++spill_pos;
2224 x86_push_reg (s->code, source_reg);
2226 x86_push_reg (s->code, dest_reg);
2228 if (source_reg != X86_ESI) {
2230 x86_mov_reg_membase (s->code, X86_ESI, X86_ESP, (source_offset-1)<<2, 4);
2232 x86_mov_reg_reg (s->code, X86_ESI, source_reg, 4);
2234 if (dest_reg != X86_EDI) {
2236 x86_mov_reg_membase (s->code, X86_EDI, X86_ESP, (dest_offset-1)<<2, 4);
2238 x86_mov_reg_reg (s->code, X86_EDI, dest_reg, 4);
2241 x86_mov_reg_imm (s->code, X86_ECX, count >> 2);
2243 x86_prefix (s->code, X86_REP_PREFIX);
2244 x86_movsd (s->code);
2246 switch (count & 3) {
2248 x86_mov_reg_membase (s->code, sreg, X86_ESI, 0, 1);
2249 x86_mov_membase_reg (s->code, X86_EDI, 0, sreg, 1);
2252 x86_mov_reg_membase (s->code, sreg, X86_ESI, 0, 2);
2253 x86_mov_membase_reg (s->code, X86_EDI, 0, sreg, 2);
2256 x86_mov_reg_membase (s->code, sreg, X86_ESI, 0, 2);
2257 x86_mov_membase_reg (s->code, X86_EDI, 0, sreg, 2);
2258 x86_mov_reg_membase (s->code, sreg, X86_ESI, 2, 1);
2259 x86_mov_membase_reg (s->code, X86_EDI, 2, sreg, 1);
2265 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, spill_pos<<2);
2268 x86_pop_reg (s->code, X86_EDI);
2270 x86_pop_reg (s->code, X86_ESI);
2275 MBCOND (mono_inline_memcpy);
2279 stmt: CPBLK (reg, CPSRC (reg, reg)) {
2280 int dest_reg = tree->left->reg1;
2281 int source_reg = tree->right->left->reg1;
2282 int size_reg = tree->right->right->reg1;
2283 int spill_pos = 0, size_offset = 0, dest_offset = 0, source_offset = 0;
2284 int save_esi = FALSE, save_edi = FALSE;
2286 if (!mono_inline_memcpy) {
2287 x86_push_reg (s->code, size_reg);
2288 x86_push_reg (s->code, source_reg);
2289 x86_push_reg (s->code, dest_reg);
2290 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, memmove);
2291 x86_call_code (s->code, 0);
2292 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
2294 if (dest_reg != X86_ESI && source_reg != X86_ESI && size_reg != X86_ESI &&
2295 mono_regset_reg_used (s->rs, X86_ESI))
2297 if (dest_reg != X86_EDI && source_reg != X86_EDI && size_reg != X86_EDI &&
2298 mono_regset_reg_used (s->rs, X86_EDI))
2302 x86_push_reg (s->code, X86_ESI);
2304 x86_push_reg (s->code, X86_EDI);
2306 if (size_reg == X86_EDI || size_reg == X86_ESI) {
2307 size_offset = ++spill_pos;
2309 if (dest_reg == X86_ECX || dest_reg == X86_ESI) {
2310 dest_offset = ++spill_pos;
2312 if (source_reg == X86_ECX || source_reg == X86_EDI) {
2313 source_offset = ++spill_pos;
2317 x86_push_reg (s->code, source_reg);
2319 x86_push_reg (s->code, dest_reg);
2321 x86_push_reg (s->code, size_reg);
2323 if (source_reg != X86_ESI) {
2325 x86_mov_reg_membase (s->code, X86_ESI, X86_ESP, (source_offset-1)<<2, 4);
2327 x86_mov_reg_reg (s->code, X86_ESI, source_reg, 4);
2329 if (dest_reg != X86_EDI) {
2331 x86_mov_reg_membase (s->code, X86_EDI, X86_ESP, (dest_offset-1)<<2, 4);
2333 x86_mov_reg_reg (s->code, X86_EDI, dest_reg, 4);
2335 if (size_reg != X86_ECX) {
2337 x86_mov_reg_membase (s->code, X86_ECX, X86_ESP, (size_offset-1)<<2, 4);
2339 x86_mov_reg_reg (s->code, X86_ECX, size_reg, 4);
2342 x86_push_reg (s->code, X86_ECX);
2343 x86_shift_reg_imm (s->code, X86_SHR, X86_ECX, 2);
2347 // move whole dwords first
2348 x86_prefix (s->code, X86_REP_PREFIX);
2349 x86_movsd (s->code);
2351 x86_pop_reg (s->code, X86_ECX);
2352 x86_alu_reg_imm (s->code, X86_AND, X86_ECX, 3);
2354 // move remaining bytes (if any)
2355 x86_prefix (s->code, X86_REP_PREFIX);
2356 x86_movsb (s->code);
2358 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, spill_pos<<2);
2361 x86_pop_reg (s->code, X86_EDI);
2363 x86_pop_reg (s->code, X86_ESI);
2367 stmt: INITBLK (reg, CPSRC (reg, CONST_I4)) {
2368 int dest_reg = tree->left->reg1;
2369 int value_reg = tree->right->left->reg1;
2370 int size = tree->right->right->data.i;
2371 int spill_pos = 0, dest_offset = 0, value_offset = 0;
2372 int save_edi = FALSE;
2378 if (mono_inline_memcpy) {
2380 if (dest_reg != X86_EDI && value_reg != X86_EDI &&
2381 mono_regset_reg_used (s->rs, X86_EDI)) {
2383 x86_push_reg (s->code, X86_EDI);
2386 if (dest_reg == X86_ECX || dest_reg == X86_EAX) {
2387 dest_offset = ++spill_pos;
2389 if (value_reg == X86_ECX || value_reg == X86_EDI) {
2390 value_offset = ++spill_pos;
2394 x86_push_reg (s->code, value_reg);
2396 x86_push_reg (s->code, dest_reg);
2398 if (value_reg != X86_EAX) {
2400 x86_mov_reg_membase (s->code, X86_EAX, X86_ESP, (value_offset-1)<<2, 4);
2402 x86_mov_reg_reg (s->code, X86_EAX, value_reg, 4);
2404 if (dest_reg != X86_EDI) {
2406 x86_mov_reg_membase (s->code, X86_EDI, X86_ESP, (dest_offset-1)<<2, 4);
2408 x86_mov_reg_reg (s->code, X86_EDI, dest_reg, 4);
2411 x86_widen_reg (s->code, X86_EAX, X86_EAX, FALSE, FALSE);
2412 x86_mov_reg_reg (s->code, X86_EDX, X86_EAX, 4);
2413 x86_shift_reg_imm (s->code, X86_SHL, X86_EAX, 8);
2414 x86_alu_reg_reg (s->code, X86_OR, X86_EAX, X86_EDX);
2415 x86_mov_reg_reg (s->code, X86_EDX, X86_EAX, 4);
2416 x86_shift_reg_imm (s->code, X86_SHL, X86_EAX, 16);
2417 x86_alu_reg_reg (s->code, X86_OR, X86_EAX, X86_EDX);
2420 x86_mov_reg_imm (s->code, X86_ECX, i);
2422 x86_prefix (s->code, X86_REP_PREFIX);
2423 x86_stosd (s->code);
2426 for (i = 0; i < j; i++)
2427 x86_stosb (s->code);
2429 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, spill_pos<<2);
2432 x86_pop_reg (s->code, X86_EDI);
2435 x86_push_imm (s->code, size);
2436 x86_push_reg (s->code, value_reg);
2437 x86_push_reg (s->code, dest_reg);
2438 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, memset);
2439 x86_call_code (s->code, 0);
2440 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
2443 MBCOND (mono_inline_memcpy);
2447 stmt: INITBLK (reg, CPSRC (reg, reg)) {
2448 int dest_reg = tree->left->reg1;
2449 int value_reg = tree->right->left->reg1;
2450 int size_reg = tree->right->right->reg1;
2451 int spill_pos = 0, size_offset = 0, dest_offset = 0, value_offset = 0;
2452 int save_edi = FALSE;
2454 if (mono_inline_memcpy) {
2456 if (dest_reg != X86_EDI && size_reg != X86_EDI && size_reg != X86_EDI &&
2457 mono_regset_reg_used (s->rs, X86_EDI)) {
2459 x86_push_reg (s->code, X86_EDI);
2462 if (size_reg == X86_EDI || size_reg == X86_EAX) {
2463 size_offset = ++spill_pos;
2465 if (dest_reg == X86_ECX || dest_reg == X86_EAX) {
2466 dest_offset = ++spill_pos;
2468 if (value_reg == X86_ECX || value_reg == X86_EDI) {
2469 value_offset = ++spill_pos;
2473 x86_push_reg (s->code, value_reg);
2475 x86_push_reg (s->code, dest_reg);
2477 x86_push_reg (s->code, size_reg);
2479 if (value_reg != X86_EAX) {
2481 x86_mov_reg_membase (s->code, X86_EAX, X86_ESP, (value_offset-1)<<2, 4);
2483 x86_mov_reg_reg (s->code, X86_EAX, value_reg, 4);
2485 if (dest_reg != X86_EDI) {
2487 x86_mov_reg_membase (s->code, X86_EDI, X86_ESP, (dest_offset-1)<<2, 4);
2489 x86_mov_reg_reg (s->code, X86_EDI, dest_reg, 4);
2491 if (size_reg != X86_ECX) {
2493 x86_mov_reg_membase (s->code, X86_ECX, X86_ESP, (size_offset-1)<<2, 4);
2495 x86_mov_reg_reg (s->code, X86_ECX, size_reg, 4);
2498 x86_widen_reg (s->code, X86_EAX, X86_EAX, FALSE, FALSE);
2499 x86_mov_reg_reg (s->code, X86_EDX, X86_EAX, 4);
2500 x86_shift_reg_imm (s->code, X86_SHL, X86_EAX, 8);
2501 x86_alu_reg_reg (s->code, X86_OR, X86_EAX, X86_EDX);
2502 x86_mov_reg_reg (s->code, X86_EDX, X86_EAX, 4);
2503 x86_shift_reg_imm (s->code, X86_SHL, X86_EAX, 16);
2504 x86_alu_reg_reg (s->code, X86_OR, X86_EAX, X86_EDX);
2506 x86_push_reg (s->code, X86_ECX);
2507 x86_shift_reg_imm (s->code, X86_SHR, X86_ECX, 2);
2510 // init whole dwords first
2511 x86_prefix (s->code, X86_REP_PREFIX);
2512 x86_stosd (s->code);
2514 x86_pop_reg (s->code, X86_ECX);
2515 x86_alu_reg_imm (s->code, X86_AND, X86_ECX, 3);
2517 // init remaining bytes (if any)
2518 x86_prefix (s->code, X86_REP_PREFIX);
2519 x86_stosb (s->code);
2521 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, spill_pos<<2);
2524 x86_pop_reg (s->code, X86_EDI);
2527 x86_push_reg (s->code, size_reg);
2528 x86_push_reg (s->code, value_reg);
2529 x86_push_reg (s->code, dest_reg);
2530 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, memset);
2531 x86_call_code (s->code, 0);
2532 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
2541 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bb);
2542 x86_jump32 (s->code, 0);
2545 cflags: COMPARE (reg, LDIND_I4 (ADDR_L)) {
2546 int treg = VARINFO (s, tree->right->left->data.i).reg;
2547 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, treg);
2549 MBCOND ((VARINFO (data, tree->right->left->data.i).reg >= 0));
2553 cflags: COMPARE (LDIND_I4 (ADDR_L), CONST_I4) {
2554 int treg = VARINFO (s, tree->left->left->data.i).reg;
2555 x86_alu_reg_imm (s->code, X86_CMP, treg, tree->right->data.i);
2557 MBCOND ((VARINFO (data, tree->left->left->data.i).reg >= 0));
2561 cflags: COMPARE (LDIND_I4 (ADDR_L), reg) {
2562 int treg = VARINFO (s, tree->left->left->data.i).reg;
2563 x86_alu_reg_reg (s->code, X86_CMP, treg, tree->right->reg1);
2565 MBCOND ((VARINFO (data, tree->left->left->data.i).reg >= 0));
2569 cflags: COMPARE (LDIND_I4 (ADDR_L), CONST_I4) {
2570 int offset = VARINFO (s, tree->left->left->data.i).offset;
2571 x86_alu_membase_imm (s->code, X86_CMP, X86_EBP, offset, tree->right->data.i);
2573 MBCOND ((VARINFO (data, tree->left->left->data.i).reg < 0));
2577 cflags: COMPARE (reg, CONST_I4) {
2578 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
2581 cflags: COMPARE (reg, reg) {
2582 x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
2586 stmt: CBRANCH (cflags) {
2587 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
2589 switch (tree->data.bi.cond) {
2591 x86_branch32 (s->code, X86_CC_LT, 0, TRUE);
2594 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
2597 x86_branch32 (s->code, X86_CC_GT, 0, TRUE);
2600 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
2603 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
2606 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
2609 x86_branch32 (s->code, X86_CC_GE, 0, TRUE);
2612 x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
2615 x86_branch32 (s->code, X86_CC_LE, 0, TRUE);
2618 x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
2621 g_assert_not_reached ();
2625 stmt: BRTRUE (LDIND_I4 (ADDR_L)) {
2626 int treg = VARINFO (s, tree->left->left->data.i).reg;
2627 int offset = VARINFO (s, tree->left->left->data.i).offset;
2630 x86_test_reg_reg (s->code, treg, treg);
2632 x86_alu_membase_imm (s->code, X86_CMP, X86_EBP, offset, 0);
2634 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bb);
2635 x86_branch32 (s->code, X86_CC_NE, 0, TRUE);
2638 stmt: BRTRUE (reg) {
2639 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
2640 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bb);
2641 x86_branch32 (s->code, X86_CC_NE, 0, TRUE);
2644 stmt: BRFALSE (LDIND_I4 (ADDR_L)) {
2645 int treg = VARINFO (s, tree->left->left->data.i).reg;
2646 int offset = VARINFO (s, tree->left->left->data.i).offset;
2649 x86_test_reg_reg (s->code, treg, treg);
2651 x86_alu_membase_imm (s->code, X86_CMP, X86_EBP, offset, 0);
2653 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bb);
2654 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
2656 //{static int cx= 0; printf ("CX1 %5d\n", cx++);}
2659 stmt: BRFALSE (reg) {
2660 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
2661 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bb);
2662 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
2666 x86_breakpoint (s->code);
2670 if (tree->left->reg1 != X86_EAX)
2671 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
2673 if (!tree->last_instr) {
2674 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_EPILOG, NULL);
2675 x86_jump32 (s->code, 0);
2680 if (!tree->last_instr) {
2681 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_EPILOG, NULL);
2682 x86_jump32 (s->code, 0);
2686 stmt: ARG_I4 (LDIND_I4 (addr)) {
2687 MBTree *at = tree->left->left;
2688 int pad = tree->data.arg_info.pad;
2692 switch (at->data.ainfo.amode) {
2695 x86_push_mem (s->code, at->data.ainfo.offset);
2699 x86_push_membase (s->code, at->data.ainfo.basereg, at->data.ainfo.offset);
2702 x86_push_memindex (s->code, X86_NOBASEREG, at->data.ainfo.offset,
2703 at->data.ainfo.indexreg, at->data.ainfo.shift);
2706 x86_push_memindex (s->code, at->data.ainfo.basereg,
2707 at->data.ainfo.offset, at->data.ainfo.indexreg,
2708 at->data.ainfo.shift);
2713 stmt: ARG_I4 (LDIND_I4 (ADDR_L)) {
2714 int treg = VARINFO (s, tree->left->left->data.i).reg;
2715 int pad = tree->data.arg_info.pad;
2718 x86_push_reg (s->code, treg);
2720 MBCOND ((VARINFO (data, tree->left->left->data.i).reg >= 0));
2724 stmt: ARG_I4 (reg) {
2725 int pad = tree->data.arg_info.pad;
2728 x86_push_reg (s->code, tree->left->reg1);
2731 stmt: ARG_I4 (ADDR_G) {
2732 int pad = tree->data.arg_info.pad;
2735 x86_push_imm (s->code, tree->left->data.p);
2738 stmt: ARG_I4 (CONST_I4) "MB_USE_OPT1(0)" {
2739 int pad = tree->data.arg_info.pad;
2742 x86_push_imm (s->code, tree->left->data.i);
2746 PRINT_REG ("THIS", tree->reg1);
2749 reg: CHECKTHIS (reg) {
2750 /* try to access the vtable - this will raise an exception
2751 * if the object is NULL */
2752 x86_alu_membase_imm (s->code, X86_CMP, tree->left->reg1, 0, 0);
2753 if (tree->reg1 != tree->left->reg1)
2754 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
2757 stmt: CHECKTHIS (reg) {
2758 x86_alu_membase_imm (s->code, X86_CMP, tree->left->reg1, 0, 0);
2765 /* restore callee saved registers */
2766 if (mono_regset_reg_used (s->rs, X86_EBX)) {
2767 x86_mov_reg_membase (s->code, X86_EBX, X86_EBP, pos, 4);
2770 if (mono_regset_reg_used (s->rs, X86_EDI)) {
2771 x86_mov_reg_membase (s->code, X86_EDI, X86_EBP, pos, 4);
2774 if (mono_regset_reg_used (s->rs, X86_ESI)) {
2775 x86_mov_reg_membase (s->code, X86_ESI, X86_EBP, pos, 4);
2778 /* restore ESP/EBP */
2779 x86_leave (s->code);
2781 /* jump to the method */
2782 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->data.p);
2783 x86_jump32 (s->code, 0);
2788 reg: CALL_I4 (this, reg) {
2790 int lreg = tree->left->reg1;
2791 int rreg = tree->right->reg1;
2793 if (lreg == treg || rreg == treg)
2795 if (lreg == treg || rreg == treg)
2797 if (lreg == treg || rreg == treg)
2798 mono_assert_not_reached ();
2802 x86_call_reg (s->code, rreg);
2806 mono_assert (tree->reg1 == X86_EAX);
2809 reg: CALL_I4 (this, ADDR_G) {
2810 int lreg = tree->left->reg1;
2818 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->right->data.p);
2819 x86_call_code (s->code, 0);
2823 mono_assert (tree->reg1 == X86_EAX);
2826 reg: LDVIRTFTN (reg, INTF_ADDR) {
2827 /* we cant return the value in the vtable, because it can be
2828 * a magic trampoline, and we cant pass that to the outside world */
2830 if (tree->reg1 != X86_EAX)
2831 x86_push_reg (s->code, X86_EAX);
2832 x86_push_reg (s->code, X86_ECX);
2833 x86_push_reg (s->code, X86_EDX);
2835 x86_push_imm (s->code, tree->right->data.m->klass->interface_id);
2836 x86_push_reg (s->code, tree->left->reg1);
2837 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_ldintftn);
2838 x86_call_code (s->code, 0);
2839 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
2841 x86_pop_reg (s->code, X86_EDX);
2842 x86_pop_reg (s->code, X86_ECX);
2843 if (tree->reg1 != X86_EAX) {
2844 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
2845 x86_pop_reg (s->code, X86_EAX);
2849 reg: CALL_I4 (this, INTF_ADDR) {
2850 int lreg = tree->left->reg1;
2858 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2859 x86_mov_reg_membase (s->code, lreg, lreg,
2860 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
2861 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
2862 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
2866 mono_assert (tree->reg1 == X86_EAX);
2869 reg: LDVIRTFTN (reg, VFUNC_ADDR) {
2870 /* we cant return the value in the vtable, because it can be
2871 * a magic trampoline, and we cant pass that to the outside world */
2873 if (tree->reg1 != X86_EAX)
2874 x86_push_reg (s->code, X86_EAX);
2875 x86_push_reg (s->code, X86_ECX);
2876 x86_push_reg (s->code, X86_EDX);
2878 x86_push_imm (s->code, tree->right->data.m->slot);
2879 x86_push_reg (s->code, tree->left->reg1);
2880 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_ldvirtftn);
2881 x86_call_code (s->code, 0);
2882 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
2884 x86_pop_reg (s->code, X86_EDX);
2885 x86_pop_reg (s->code, X86_ECX);
2886 if (tree->reg1 != X86_EAX) {
2887 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
2888 x86_pop_reg (s->code, X86_EAX);
2893 if (tree->reg1 != X86_EAX)
2894 x86_push_reg (s->code, X86_EAX);
2895 x86_push_reg (s->code, X86_ECX);
2896 x86_push_reg (s->code, X86_EDX);
2898 x86_push_imm (s->code, tree->data.m);
2899 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_ldftn);
2900 x86_call_code (s->code, 0);
2901 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
2903 x86_pop_reg (s->code, X86_EDX);
2904 x86_pop_reg (s->code, X86_ECX);
2905 if (tree->reg1 != X86_EAX) {
2906 x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
2907 x86_pop_reg (s->code, X86_EAX);
2912 reg: CALL_I4 (this, VFUNC_ADDR) {
2913 int lreg = tree->left->reg1;
2921 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2922 x86_call_virtual (s->code, lreg,
2923 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
2927 mono_assert (tree->reg1 == X86_EAX);
2930 stmt: CALL_VOID (this, ADDR_G) {
2931 int lreg = tree->left->reg1;
2939 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->right->data.p);
2940 x86_call_code (s->code, 0);
2945 stmt: CALL_VOID (this, reg) {
2947 int lreg = tree->left->reg1;
2948 int rreg = tree->right->reg1;
2950 if (lreg == treg || rreg == treg)
2952 if (lreg == treg || rreg == treg)
2954 if (lreg == treg || rreg == treg)
2955 mono_assert_not_reached ();
2959 x86_call_reg (s->code, tree->right->reg1);
2964 stmt: CALL_VOID (this, INTF_ADDR) {
2965 int lreg = tree->left->reg1;
2973 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2974 x86_mov_reg_membase (s->code, lreg, lreg,
2975 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
2976 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
2977 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
2982 stmt: CALL_VOID (this, VFUNC_ADDR) {
2983 int lreg = tree->left->reg1;
2991 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
2992 x86_call_virtual (s->code, lreg,
2993 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
2998 stmt: SWITCH (reg) {
3000 guint32 *jt = (guint32 *)tree->data.p;
3002 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, jt [0]);
3003 offset = 6 + (guint32)s->code;
3004 x86_branch32 (s->code, X86_CC_GE, jt [jt [0] + 1] - offset, FALSE);
3006 x86_mov_reg_memindex (s->code, X86_EAX, X86_NOBASEREG,
3007 tree->data.i + 4, tree->left->reg1, 2, 4);
3008 x86_jump_reg (s->code, X86_EAX);
3015 reg: CONV_I1 (lreg) {
3016 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, FALSE);
3019 reg: CONV_U1 (lreg) {
3020 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, FALSE);
3023 reg: CONV_I2 (lreg) {
3024 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, TRUE, TRUE);
3027 reg: CONV_U2 (lreg) {
3028 x86_widen_reg (s->code, tree->reg1, tree->left->reg1, FALSE, TRUE);
3031 reg: CONV_I4 (lreg) {
3032 if (tree->reg1 != tree->left->reg1)
3033 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3036 reg: CONV_U4 (lreg) {
3037 if (tree->reg1 != tree->left->reg1)
3038 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3042 reg: CONV_OVF_I4 (lreg){
3043 guint8 *start = s->code;
3044 guchar* o1, *o2, *o3, *o4, *o5;
3048 * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000
3050 for (i = 0; i < 2; i++) {
3053 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
3055 /* If the low word top bit is set, see if we are negative */
3056 x86_branch8 (s->code, X86_CC_LT, o3 - o1, TRUE);
3059 /* We are not negative (no top bit set, check for our top word to be zero */
3060 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
3061 x86_branch8 (s->code, X86_CC_EQ, o4 - o2, TRUE);
3064 /* throw exception */
3065 x86_push_imm (s->code, "OverflowException");
3066 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS,
3067 arch_get_throw_exception_by_name ());
3068 x86_call_code (s->code, 0);
3071 /* our top bit is set, check that top word is 0xfffffff */
3072 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg2, 0xffffffff);
3075 /* nope, emit exception */
3076 x86_branch8 (s->code, X86_CC_NE, o2 - o5, TRUE);
3079 if (tree->reg1 != tree->left->reg1)
3080 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3083 reg: CONV_OVF_I4 (lreg){
3084 guint8 *br [3], *label [1];
3087 * Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000
3089 x86_test_reg_reg (s->code, tree->left->reg1, tree->left->reg1);
3091 /* If the low word top bit is set, see if we are negative */
3092 br [0] = s->code; x86_branch8 (s->code, X86_CC_LT, 0, TRUE);
3094 /* We are not negative (no top bit set, check for our top word to be zero */
3095 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
3096 br [1] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, TRUE);
3097 label [0] = s->code;
3099 /* throw exception */
3100 x86_push_imm (s->code, "OverflowException");
3101 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS,
3102 arch_get_throw_exception_by_name ());
3103 x86_call_code (s->code, 0);
3105 x86_patch (br [0], s->code);
3106 /* our top bit is set, check that top word is 0xfffffff */
3107 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg2, 0xffffffff);
3109 x86_patch (br [1], s->code);
3110 /* nope, emit exception */
3111 br [2] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3112 x86_patch (br [2], label [0]);
3114 if (tree->reg1 != tree->left->reg1)
3115 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3118 reg: CONV_OVF_U4 (lreg) {
3119 /* Keep in sync with CONV_OVF_I4_UN below, they are the same on 32-bit machines */
3120 /* top word must be 0 */
3121 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
3122 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
3123 if (tree->reg1 != tree->left->reg1)
3124 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3127 reg: CONV_OVF_I4_UN (lreg) {
3128 /* Keep in sync with CONV_OVF_U4 above, they are the same on 32-bit machines */
3129 /* top word must be 0 */
3130 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
3131 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
3132 if (tree->reg1 != tree->left->reg1)
3133 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3139 x86_mov_reg_imm (s->code, tree->reg1, *((gint32 *)&tree->data.p));
3140 x86_mov_reg_imm (s->code, tree->reg2, *((gint32 *)&tree->data.p + 1));
3143 lreg: CONV_I8 (CONST_I4) {
3144 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
3146 if (tree->left->data.i >= 0)
3147 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
3149 x86_mov_reg_imm (s->code, tree->reg2, -1);
3152 lreg: CONV_I8 (reg) {
3155 if (tree->reg1 != tree->left->reg1)
3156 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3158 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
3159 x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
3160 x86_branch8 (s->code, X86_CC_GE, 5, TRUE);
3162 x86_mov_reg_imm (s->code, tree->reg2, -1);
3163 mono_assert ((s->code - i1) == 5);
3166 lreg: CONV_U8 (CONST_I4) 1 {
3167 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
3168 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
3171 lreg: CONV_U8 (reg) {
3172 if (tree->reg1 != tree->left->reg1)
3173 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3174 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
3177 lreg: CONV_OVF_U8 (CONST_I4) {
3178 if (tree->left->data.i < 0){
3179 x86_push_imm (s->code, "OverflowException");
3180 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS,
3181 arch_get_throw_exception_by_name ());
3182 x86_call_code (s->code, 0);
3184 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
3185 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
3189 lreg: CONV_OVF_I8_UN (CONST_I4) {
3190 x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
3191 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
3194 lreg: CONV_OVF_U8 (reg) {
3195 x86_test_reg_imm (s->code, tree->left->reg1, 0x8000000);
3196 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, TRUE, "OverflowException");
3198 if (tree->reg1 != tree->left->reg1)
3199 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3200 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
3203 lreg: CONV_OVF_I8_UN (reg) {
3204 /* Convert uint value into int64, we pass everything */
3205 if (tree->reg1 != tree->left->reg1)
3206 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3207 x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
3210 stmt: STIND_I8 (addr, lreg) {
3212 switch (tree->left->data.ainfo.amode) {
3215 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset, tree->right->reg1, 4);
3216 x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset + 4, tree->right->reg2, 4);
3220 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
3221 tree->left->data.ainfo.offset, tree->right->reg1, 4);
3222 x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg,
3223 tree->left->data.ainfo.offset + 4, tree->right->reg2, 4);
3226 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset,
3227 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
3228 tree->right->reg1, 4);
3229 x86_mov_memindex_reg (s->code, X86_NOBASEREG, tree->left->data.ainfo.offset + 4,
3230 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
3231 tree->right->reg2, 4);
3234 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
3235 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
3236 tree->right->reg1, 4);
3237 x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset + 4,
3238 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
3239 tree->right->reg2, 4);
3244 stmt: REMOTE_STIND_I8 (reg, lreg) {
3248 x86_push_reg (s->code, tree->right->reg1);
3249 x86_mov_reg_membase (s->code, tree->right->reg1, tree->left->reg1, 0, 4);
3250 x86_alu_membase_imm (s->code, X86_CMP, tree->right->reg1, 0, ((int)mono_defaults.transparent_proxy_class));
3251 x86_pop_reg (s->code, tree->right->reg1);
3253 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3255 /* this is a transparent proxy - remote the call */
3257 /* save value to stack */
3258 x86_push_reg (s->code, tree->right->reg2);
3259 x86_push_reg (s->code, tree->right->reg1);
3261 x86_push_reg (s->code, X86_ESP);
3262 x86_push_imm (s->code, tree->data.fi.field);
3263 x86_push_imm (s->code, tree->data.fi.klass);
3264 x86_push_reg (s->code, tree->left->reg1);
3265 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
3266 x86_call_code (s->code, 0);
3267 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 24);
3269 br [1] = s->code; x86_jump8 (s->code, 0);
3271 x86_patch (br [0], s->code);
3272 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
3273 tree->data.fi.field->offset;
3274 x86_mov_membase_reg (s->code, tree->left->reg1, offset, tree->right->reg1, 4);
3275 x86_mov_membase_reg (s->code, tree->left->reg1, offset + 4, tree->right->reg2, 4);
3277 x86_patch (br [1], s->code);
3281 # an addr can use two address register (base and index register). The must take care
3282 # that we do not override them (thus the use of x86_lea)
3283 lreg: LDIND_I8 (addr) {
3285 switch (tree->left->data.ainfo.amode) {
3288 x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
3289 x86_mov_reg_mem (s->code, tree->reg2, tree->left->data.ainfo.offset + 4, 4);
3293 x86_lea_membase (s->code, tree->reg2, tree->left->data.ainfo.basereg,
3294 tree->left->data.ainfo.offset);
3295 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
3296 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
3299 x86_lea_memindex (s->code, tree->reg2, X86_NOBASEREG, tree->left->data.ainfo.offset,
3300 tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift);
3301 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
3302 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
3305 x86_lea_memindex (s->code, tree->reg2, tree->left->data.ainfo.basereg,
3306 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
3307 tree->left->data.ainfo.shift);
3308 x86_mov_reg_membase (s->code, tree->reg1, tree->reg2, 0, 4);
3309 x86_mov_reg_membase (s->code, tree->reg2, tree->reg2, 4, 4);
3312 PRINT_REG ("LDIND_I8_0", tree->reg1);
3313 PRINT_REG ("LDIND_I8_1", tree->reg2);
3316 lreg: SHR (lreg, CONST_I4) {
3317 if (tree->right->data.i < 32) {
3318 x86_shrd_reg_imm (s->code, tree->left->reg1, tree->left->reg2, tree->right->data.i);
3319 x86_shift_reg_imm (s->code, X86_SAR, tree->left->reg2, tree->right->data.i);
3320 if (tree->reg1 != tree->left->reg1)
3321 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3322 if (tree->reg2 != tree->left->reg2)
3323 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
3324 } else if (tree->right->data.i < 64) {
3325 if (tree->reg1 != tree->left->reg2)
3326 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg2, 4);
3327 if (tree->reg2 != tree->left->reg2)
3328 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
3329 x86_shift_reg_imm (s->code, X86_SAR, tree->reg2, 31);
3330 x86_shift_reg_imm (s->code, X86_SAR, tree->reg1, (tree->right->data.i - 32));
3331 } /* else unspecified result */
3334 lreg: SHR_UN (lreg, CONST_I4) {
3335 if (tree->right->data.i < 32) {
3336 x86_shrd_reg_imm (s->code, tree->left->reg1, tree->left->reg2, tree->right->data.i);
3337 x86_shift_reg_imm (s->code, X86_SHR, tree->left->reg2, tree->right->data.i);
3338 if (tree->reg1 != tree->left->reg1)
3339 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3340 if (tree->reg2 != tree->left->reg2)
3341 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
3342 } else if (tree->right->data.i < 64) {
3343 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg2, 4);
3344 x86_shift_reg_imm (s->code, X86_SHR, tree->reg1, (tree->right->data.i - 32));
3345 x86_mov_reg_imm (s->code, tree->reg2, 0);
3346 } /* else unspecified result */
3349 lreg: SHR (lreg, reg) {
3352 if (tree->right->reg1 != X86_ECX)
3353 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
3355 x86_shrd_reg (s->code, tree->left->reg1, tree->left->reg2);
3356 x86_shift_reg (s->code, X86_SAR, tree->left->reg2);
3357 x86_test_reg_imm (s->code, X86_ECX, 32);
3358 br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
3359 x86_mov_reg_reg (s->code, tree->left->reg1, tree->left->reg2, 4);
3360 x86_shift_reg_imm (s->code, X86_SAR, tree->reg2, 31);
3361 x86_patch (br [0], s->code);
3363 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3366 lreg: SHR_UN (lreg, reg) {
3369 if (tree->right->reg1 != X86_ECX)
3370 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
3372 x86_shrd_reg (s->code, tree->left->reg1, tree->left->reg2);
3373 x86_shift_reg (s->code, X86_SHR, tree->left->reg2);
3374 x86_test_reg_imm (s->code, X86_ECX, 32);
3375 br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
3376 x86_mov_reg_reg (s->code, tree->left->reg1, tree->left->reg2, 4);
3377 x86_shift_reg_imm (s->code, X86_SHR, tree->reg2, 31);
3378 x86_patch (br [0], s->code);
3380 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3383 lreg: SHL (lreg, CONST_I4) {
3384 if (tree->right->data.i < 32) {
3385 x86_shld_reg_imm (s->code, tree->left->reg2, tree->left->reg1, tree->right->data.i);
3386 x86_shift_reg_imm (s->code, X86_SHL, tree->left->reg1, tree->right->data.i);
3387 if (tree->reg1 != tree->left->reg1)
3388 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
3389 if (tree->reg2 != tree->left->reg2)
3390 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
3391 } else if (tree->right->data.i < 64) {
3392 x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg1, 4);
3393 x86_shift_reg_imm (s->code, X86_SHL, tree->reg2, (tree->right->data.i - 32));
3394 x86_alu_reg_reg (s->code, X86_XOR, tree->reg1, tree->reg1);
3395 } /* else unspecified result */
3398 lreg: SHL (lreg, reg) {
3401 if (tree->right->reg1 != X86_ECX)
3402 x86_mov_reg_reg (s->code, X86_ECX, tree->right->reg1, 4);
3404 x86_shld_reg (s->code, tree->left->reg2, tree->left->reg1);
3405 x86_shift_reg (s->code, X86_SHL, tree->left->reg1);
3406 x86_test_reg_imm (s->code, X86_ECX, 32);
3407 br [0] = s->code; x86_branch8 (s->code, X86_CC_EQ, 0, FALSE);
3408 x86_mov_reg_reg (s->code, tree->left->reg2, tree->left->reg1, 4);
3409 x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->left->reg1);
3410 x86_patch (br [0], s->code);
3412 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3415 lreg: ADD (lreg, lreg) {
3416 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
3417 x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
3419 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3422 lreg: ADD_OVF (lreg, lreg) {
3423 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
3424 x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
3425 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
3427 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3430 lreg: ADD_OVF_UN (lreg, lreg) {
3431 x86_alu_reg_reg (s->code, X86_ADD, tree->left->reg1, tree->right->reg1);
3432 x86_alu_reg_reg (s->code, X86_ADC, tree->left->reg2, tree->right->reg2);
3433 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
3435 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3438 lreg: SUB (lreg, lreg) {
3439 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
3440 x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
3442 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3445 lreg: SUB_OVF (lreg, lreg) {
3446 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
3447 x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
3448 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NO, TRUE, "OverflowException");
3450 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3453 lreg: SUB_OVF_UN (lreg, lreg) {
3454 x86_alu_reg_reg (s->code, X86_SUB, tree->left->reg1, tree->right->reg1);
3455 x86_alu_reg_reg (s->code, X86_SBB, tree->left->reg2, tree->right->reg2);
3456 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NC, FALSE, "OverflowException");
3458 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3461 lreg: AND (lreg, lreg) {
3462 x86_alu_reg_reg (s->code, X86_AND, tree->left->reg1, tree->right->reg1);
3463 x86_alu_reg_reg (s->code, X86_AND, tree->left->reg2, tree->right->reg2);
3465 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3468 lreg: OR (lreg, lreg) {
3469 x86_alu_reg_reg (s->code, X86_OR, tree->left->reg1, tree->right->reg1);
3470 x86_alu_reg_reg (s->code, X86_OR, tree->left->reg2, tree->right->reg2);
3472 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3475 lreg: XOR (lreg, lreg) {
3476 x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg1, tree->right->reg1);
3477 x86_alu_reg_reg (s->code, X86_XOR, tree->left->reg2, tree->right->reg2);
3479 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3483 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3485 x86_neg_reg (s->code, tree->reg1);
3486 x86_alu_reg_imm (s->code, X86_ADC, tree->reg2, 0);
3487 x86_neg_reg (s->code, tree->reg2);
3491 MOVE_LREG (tree->reg1, tree->reg2, tree->left->reg1, tree->left->reg2);
3493 x86_not_reg (s->code, tree->reg1);
3494 x86_not_reg (s->code, tree->reg2);
3497 lreg: MUL (lreg, lreg) {
3498 if (mono_regset_reg_used (s->rs, X86_ECX))
3499 x86_push_reg (s->code, X86_ECX);
3501 x86_push_reg (s->code, tree->right->reg2);
3502 x86_push_reg (s->code, tree->right->reg1);
3503 x86_push_reg (s->code, tree->left->reg2);
3504 x86_push_reg (s->code, tree->left->reg1);
3505 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_llmult);
3506 x86_call_code (s->code, 0);
3507 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
3509 if (mono_regset_reg_used (s->rs, X86_ECX))
3510 x86_pop_reg (s->code, X86_ECX);
3512 mono_assert (tree->reg1 == X86_EAX &&
3513 tree->reg2 == X86_EDX);
3516 lreg: MUL_OVF (lreg, lreg) {
3517 if (mono_regset_reg_used (s->rs, X86_ECX))
3518 x86_push_reg (s->code, X86_ECX);
3520 x86_push_reg (s->code, tree->right->reg2);
3521 x86_push_reg (s->code, tree->right->reg1);
3522 x86_push_reg (s->code, tree->left->reg2);
3523 x86_push_reg (s->code, tree->left->reg1);
3524 /* pass a pointer to store the resulting exception -
3525 * ugly, but it works */
3526 x86_push_reg (s->code, X86_ESP);
3527 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_llmult_ovf);
3528 x86_call_code (s->code, 0);
3529 x86_mov_reg_membase (s->code, X86_ECX, X86_ESP, 4, 4);
3530 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
3531 x86_alu_reg_imm (s->code, X86_CMP, X86_ECX, 0);
3533 /* cond. emit exception */
3534 x86_branch8 (s->code, X86_CC_EQ, 7, FALSE);
3535 x86_push_reg (s->code, X86_ECX);
3536 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, arch_get_throw_exception ());
3537 x86_call_code (s->code, 0);
3539 if (mono_regset_reg_used (s->rs, X86_ECX))
3540 x86_pop_reg (s->code, X86_ECX);
3542 mono_assert (tree->reg1 == X86_EAX &&
3543 tree->reg2 == X86_EDX);
3546 lreg: MUL_OVF_UN (lreg, lreg) {
3547 if (mono_regset_reg_used (s->rs, X86_ECX))
3548 x86_push_reg (s->code, X86_ECX);
3550 x86_push_reg (s->code, tree->right->reg2);
3551 x86_push_reg (s->code, tree->right->reg1);
3552 x86_push_reg (s->code, tree->left->reg2);
3553 x86_push_reg (s->code, tree->left->reg1);
3554 /* pass a pointer to store the resulting exception -
3555 * ugly, but it works */
3556 x86_push_reg (s->code, X86_ESP);
3557 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_llmult_ovf_un);
3558 x86_call_code (s->code, 0);
3559 x86_mov_reg_membase (s->code, X86_ECX, X86_ESP, 4, 4);
3560 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
3561 x86_alu_reg_imm (s->code, X86_CMP, X86_ECX, 0);
3563 /* cond. emit exception */
3564 x86_branch8 (s->code, X86_CC_EQ, 7, FALSE);
3565 x86_push_reg (s->code, X86_ECX);
3566 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, arch_get_throw_exception ());
3567 x86_call_code (s->code, 0);
3569 if (mono_regset_reg_used (s->rs, X86_ECX))
3570 x86_pop_reg (s->code, X86_ECX);
3572 mono_assert (tree->reg1 == X86_EAX &&
3573 tree->reg2 == X86_EDX);
3576 lreg: DIV (lreg, lreg) {
3577 if (mono_regset_reg_used (s->rs, X86_ECX))
3578 x86_push_reg (s->code, X86_ECX);
3580 x86_push_reg (s->code, tree->right->reg2);
3581 x86_push_reg (s->code, tree->right->reg1);
3582 x86_push_reg (s->code, tree->left->reg2);
3583 x86_push_reg (s->code, tree->left->reg1);
3584 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_lldiv);
3585 x86_call_code (s->code, 0);
3586 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
3588 if (mono_regset_reg_used (s->rs, X86_ECX))
3589 x86_pop_reg (s->code, X86_ECX);
3591 mono_assert (tree->reg1 == X86_EAX &&
3592 tree->reg2 == X86_EDX);
3595 lreg: REM (lreg, lreg) {
3596 if (mono_regset_reg_used (s->rs, X86_ECX))
3597 x86_push_reg (s->code, X86_ECX);
3599 x86_push_reg (s->code, tree->right->reg2);
3600 x86_push_reg (s->code, tree->right->reg1);
3601 x86_push_reg (s->code, tree->left->reg2);
3602 x86_push_reg (s->code, tree->left->reg1);
3603 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_llrem);
3604 x86_call_code (s->code, 0);
3605 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
3607 if (mono_regset_reg_used (s->rs, X86_ECX))
3608 x86_pop_reg (s->code, X86_ECX);
3610 mono_assert (tree->reg1 == X86_EAX &&
3611 tree->reg2 == X86_EDX);
3614 lreg: DIV_UN (lreg, lreg) {
3615 if (mono_regset_reg_used (s->rs, X86_ECX))
3616 x86_push_reg (s->code, X86_ECX);
3618 x86_push_reg (s->code, tree->right->reg2);
3619 x86_push_reg (s->code, tree->right->reg1);
3620 x86_push_reg (s->code, tree->left->reg2);
3621 x86_push_reg (s->code, tree->left->reg1);
3622 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_lldiv_un);
3623 x86_call_code (s->code, 0);
3624 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
3626 if (mono_regset_reg_used (s->rs, X86_ECX))
3627 x86_pop_reg (s->code, X86_ECX);
3629 mono_assert (tree->reg1 == X86_EAX &&
3630 tree->reg2 == X86_EDX);
3633 lreg: REM_UN (lreg, lreg) {
3634 if (mono_regset_reg_used (s->rs, X86_ECX))
3635 x86_push_reg (s->code, X86_ECX);
3637 x86_push_reg (s->code, tree->right->reg2);
3638 x86_push_reg (s->code, tree->right->reg1);
3639 x86_push_reg (s->code, tree->left->reg2);
3640 x86_push_reg (s->code, tree->left->reg1);
3641 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_llrem_un);
3642 x86_call_code (s->code, 0);
3643 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
3645 if (mono_regset_reg_used (s->rs, X86_ECX))
3646 x86_pop_reg (s->code, X86_ECX);
3648 mono_assert (tree->reg1 == X86_EAX &&
3649 tree->reg2 == X86_EDX);
3652 lreg: CALL_I8 (this, reg) {
3654 int lreg = tree->left->reg1;
3655 int rreg = tree->right->reg1;
3657 if (lreg == treg || rreg == treg)
3659 if (lreg == treg || rreg == treg)
3661 if (lreg == treg || rreg == treg)
3662 mono_assert_not_reached ();
3666 x86_call_reg (s->code, rreg);
3670 mono_assert (tree->reg1 == X86_EAX);
3671 mono_assert (tree->reg2 == X86_EDX);
3674 lreg: CALL_I8 (this, ADDR_G) {
3675 int lreg = tree->left->reg1;
3683 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->right->data.p);
3684 x86_call_code (s->code, 0);
3688 mono_assert (tree->reg1 == X86_EAX);
3689 mono_assert (tree->reg2 == X86_EDX);
3692 lreg: CALL_I8 (this, VFUNC_ADDR) {
3693 int lreg = tree->left->reg1;
3701 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
3702 x86_call_virtual (s->code, lreg,
3703 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
3707 mono_assert (tree->reg1 == X86_EAX);
3708 mono_assert (tree->reg2 == X86_EDX);
3711 lreg: CALL_I8 (this, INTF_ADDR) {
3712 int lreg = tree->left->reg1;
3720 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
3721 x86_mov_reg_membase (s->code, lreg, lreg,
3722 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
3723 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
3724 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
3728 mono_assert (tree->reg1 == X86_EAX);
3729 mono_assert (tree->reg2 == X86_EDX);
3733 if (tree->left->reg1 != X86_EAX) {
3734 if (tree->left->reg2 != X86_EAX) {
3735 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
3736 if (tree->left->reg2 != X86_EDX)
3737 x86_mov_reg_reg (s->code, X86_EDX, tree->left->reg2, 4);
3739 x86_mov_reg_reg (s->code, X86_ECX, tree->left->reg2, 4);
3740 x86_mov_reg_reg (s->code, X86_EAX, tree->left->reg1, 4);
3741 x86_mov_reg_reg (s->code, X86_EDX, X86_ECX, 4);
3743 } else if (tree->left->reg2 != X86_EDX) {
3744 x86_mov_reg_reg (s->code, X86_EDX, tree->left->reg2, 4);
3747 if (!tree->last_instr) {
3748 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_EPILOG, NULL);
3749 x86_jump32 (s->code, 0);
3754 stmt: ARG_I8 (lreg) {
3755 int pad = tree->data.arg_info.pad;
3758 x86_push_reg (s->code, tree->left->reg2);
3759 x86_push_reg (s->code, tree->left->reg1);
3762 reg: CSET (COMPARE (lreg, lreg)) {
3764 int lreg1, lreg2, rreg1, rreg2;
3766 lreg1 = tree->left->left->reg1;
3767 lreg2 = tree->left->left->reg2;
3768 rreg1 = tree->left->right->reg1;
3769 rreg2 = tree->left->right->reg2;
3772 if (tree->data.i == CEE_CEQ) {
3773 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3774 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3775 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3776 x86_patch (br [0], s->code);
3777 x86_set_reg (s->code, X86_CC_EQ, tree->reg1, FALSE);
3778 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
3782 switch (tree->data.i) {
3784 x86_alu_reg_reg (s->code, X86_CMP, rreg2, lreg2);
3785 br [0] = s->code; x86_branch8 (s->code, X86_CC_GT, 0, TRUE);
3786 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3787 x86_alu_reg_reg (s->code, X86_CMP, rreg1, lreg1);
3788 br [2] = s->code; x86_branch8 (s->code, X86_CC_GE, 0, FALSE);
3791 x86_alu_reg_reg (s->code, X86_CMP, rreg2, lreg2);
3792 br [0] = s->code; x86_branch8 (s->code, X86_CC_GT, 0, FALSE);
3793 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3794 x86_alu_reg_reg (s->code, X86_CMP, rreg1, lreg1);
3795 br [2] = s->code; x86_branch8 (s->code, X86_CC_GE, 0, FALSE);
3798 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3799 br [0] = s->code; x86_branch8 (s->code, X86_CC_GT, 0, TRUE);
3800 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3801 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3802 br [2] = s->code; x86_branch8 (s->code, X86_CC_GE, 0, FALSE);
3805 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3806 br [0] = s->code; x86_branch8 (s->code, X86_CC_GT, 0, FALSE);
3807 br [1] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3808 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3809 br [2] = s->code; x86_branch8 (s->code, X86_CC_GE, 0, FALSE);
3812 g_assert_not_reached ();
3815 /* set result to 1 */
3816 x86_patch (br [1], s->code);
3817 x86_mov_reg_imm (s->code, tree->reg1, 1);
3818 br [3] = s->code; x86_jump8 (s->code, 0);
3820 /* set result to 0 */
3821 x86_patch (br [0], s->code);
3822 x86_patch (br [2], s->code);
3823 x86_mov_reg_imm (s->code, tree->reg1, 0);
3825 x86_patch (br [3], s->code);
3828 stmt: CBRANCH (COMPARE (lreg, lreg)) {
3830 int lreg1, lreg2, rreg1, rreg2;
3832 lreg1 = tree->left->left->reg1;
3833 lreg2 = tree->left->left->reg2;
3834 rreg1 = tree->left->right->reg1;
3835 rreg2 = tree->left->right->reg2;
3837 switch (tree->data.bi.cond) {
3839 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3840 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3841 x86_branch32 (s->code, X86_CC_LT, 0, TRUE);
3842 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3843 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3844 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3845 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
3846 x86_patch (br [0], s->code);
3849 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3850 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3851 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
3852 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3853 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3854 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3855 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
3856 x86_patch (br [0], s->code);
3859 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3860 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3861 x86_branch32 (s->code, X86_CC_GT, 0, TRUE);
3862 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3863 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3864 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3865 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
3866 x86_patch (br [0], s->code);
3869 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3870 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3871 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
3872 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3873 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3874 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3875 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
3876 x86_patch (br [0], s->code);
3879 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3880 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3881 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3882 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3883 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
3884 x86_patch (br [0], s->code);
3887 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3888 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3889 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3890 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3891 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3892 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
3895 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3896 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3897 x86_branch32 (s->code, X86_CC_GT, 0, TRUE);
3898 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3899 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3900 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3901 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3902 x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
3903 x86_patch (br [0], s->code);
3906 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3907 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3908 x86_branch32 (s->code, X86_CC_GT, 0, FALSE);
3909 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3910 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3911 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3912 x86_branch32 (s->code, X86_CC_GE, 0, FALSE);
3913 x86_patch (br [0], s->code);
3916 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3917 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3918 x86_branch32 (s->code, X86_CC_LT, 0, TRUE);
3919 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, TRUE);
3920 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3921 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3922 x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
3923 x86_patch (br [0], s->code);
3926 x86_alu_reg_reg (s->code, X86_CMP, lreg2, rreg2);
3927 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3928 x86_branch32 (s->code, X86_CC_LT, 0, FALSE);
3929 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
3930 x86_alu_reg_reg (s->code, X86_CMP, lreg1, rreg1);
3931 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
3932 x86_branch32 (s->code, X86_CC_LE, 0, FALSE);
3933 x86_patch (br [0], s->code);
3936 g_assert_not_reached ();
3943 #stmt: STLOC (CONV_I4 (freg)) {
3945 # x86_fist_pop_membase (s->code, X86_EBP, tree->data.i, FALSE);
3948 reg: CONV_I1 (freg) {
3949 if (mono_use_fast_iconv) {
3950 mono_emit_fast_iconv(s, tree);
3951 x86_widen_reg (s->code, tree->reg1, tree->reg1, TRUE, FALSE);
3953 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3954 x86_fnstcw_membase(s->code, X86_ESP, 0);
3955 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3956 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3957 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3958 x86_fldcw_membase (s->code, X86_ESP, 2);
3959 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
3960 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
3961 x86_pop_reg (s->code, tree->reg1);
3962 x86_widen_reg (s->code, tree->reg1, tree->reg1, TRUE, FALSE);
3963 x86_fldcw_membase (s->code, X86_ESP, 0);
3964 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3968 reg: CONV_U1 (freg) {
3969 if (mono_use_fast_iconv) {
3970 mono_emit_fast_iconv(s, tree);
3971 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
3973 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3974 x86_fnstcw_membase(s->code, X86_ESP, 0);
3975 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3976 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3977 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3978 x86_fldcw_membase (s->code, X86_ESP, 2);
3979 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
3980 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
3981 x86_pop_reg (s->code, tree->reg1);
3982 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
3983 x86_fldcw_membase (s->code, X86_ESP, 0);
3984 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
3988 reg: CONV_I2 (freg) {
3989 if (mono_use_fast_iconv) {
3990 mono_emit_fast_iconv(s, tree);
3991 x86_widen_reg (s->code, tree->reg1, tree->reg1, TRUE, TRUE);
3993 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
3994 x86_fnstcw_membase(s->code, X86_ESP, 0);
3995 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
3996 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
3997 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
3998 x86_fldcw_membase (s->code, X86_ESP, 2);
3999 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
4000 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
4001 x86_pop_reg (s->code, tree->reg1);
4002 x86_widen_reg (s->code, tree->reg1, tree->reg1, TRUE, TRUE);
4003 x86_fldcw_membase (s->code, X86_ESP, 0);
4004 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
4008 reg: CONV_U2 (freg) {
4009 if (mono_use_fast_iconv) {
4010 mono_emit_fast_iconv(s, tree);
4011 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, TRUE);
4013 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
4014 x86_fnstcw_membase(s->code, X86_ESP, 0);
4015 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
4016 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
4017 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
4018 x86_fldcw_membase (s->code, X86_ESP, 2);
4019 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
4020 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
4021 x86_pop_reg (s->code, tree->reg1);
4022 x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, TRUE);
4023 x86_fldcw_membase (s->code, X86_ESP, 0);
4024 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
4028 reg: CONV_I4 (freg) {
4029 if (mono_use_fast_iconv) {
4030 mono_emit_fast_iconv(s, tree);
4032 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
4033 x86_fnstcw_membase(s->code, X86_ESP, 0);
4034 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
4035 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
4036 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
4037 x86_fldcw_membase (s->code, X86_ESP, 2);
4038 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
4039 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
4040 x86_pop_reg (s->code, tree->reg1);
4041 x86_fldcw_membase (s->code, X86_ESP, 0);
4042 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
4046 reg: CONV_U4 (freg) {
4047 if (mono_use_fast_iconv) {
4048 mono_emit_fast_iconv(s, tree);
4050 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
4051 x86_fnstcw_membase(s->code, X86_ESP, 0);
4052 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
4053 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
4054 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
4055 x86_fldcw_membase (s->code, X86_ESP, 2);
4056 x86_push_reg (s->code, X86_EAX); // SP = SP - 4
4057 x86_fist_pop_membase (s->code, X86_ESP, 0, FALSE);
4058 x86_pop_reg (s->code, tree->reg1);
4059 x86_fldcw_membase (s->code, X86_ESP, 0);
4060 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
4064 lreg: CONV_I8 (freg) {
4065 if (mono_use_fast_iconv) {
4066 mono_emit_fast_iconv_i8(s, tree);
4068 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
4069 x86_fnstcw_membase(s->code, X86_ESP, 0);
4070 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
4071 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
4072 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
4073 x86_fldcw_membase (s->code, X86_ESP, 2);
4074 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
4075 x86_fist_pop_membase (s->code, X86_ESP, 0, TRUE);
4076 x86_pop_reg (s->code, tree->reg1);
4077 x86_pop_reg (s->code, tree->reg2);
4078 x86_fldcw_membase (s->code, X86_ESP, 0);
4079 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
4083 lreg: CONV_U8 (freg) {
4084 if (mono_use_fast_iconv) {
4085 mono_emit_fast_iconv_i8(s, tree);
4087 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
4088 x86_fnstcw_membase(s->code, X86_ESP, 0);
4089 x86_mov_reg_membase (s->code, tree->reg1, X86_ESP, 0, 2);
4090 x86_alu_reg_imm (s->code, X86_OR, tree->reg1, 0xc00);
4091 x86_mov_membase_reg (s->code, X86_ESP, 2, tree->reg1, 2);
4092 x86_fldcw_membase (s->code, X86_ESP, 2);
4093 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
4094 x86_fist_pop_membase (s->code, X86_ESP, 0, TRUE);
4095 x86_pop_reg (s->code, tree->reg1);
4096 x86_pop_reg (s->code, tree->reg2);
4097 x86_fldcw_membase (s->code, X86_ESP, 0);
4098 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
4102 reg: CSET (COMPARE (freg, freg)) {
4103 int treg = tree->reg1;
4105 if (treg != X86_EAX)
4106 x86_push_reg (s->code, X86_EAX);
4108 x86_fcompp (s->code);
4109 x86_fnstsw (s->code);
4110 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
4112 switch (tree->data.i) {
4114 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
4115 x86_set_reg (s->code, X86_CC_EQ, treg, TRUE);
4116 x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
4119 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
4120 x86_set_reg (s->code, X86_CC_EQ, treg, TRUE);
4121 x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
4124 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
4125 x86_set_reg (s->code, X86_CC_EQ, treg, TRUE);
4126 x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
4129 x86_set_reg (s->code, X86_CC_EQ, treg, TRUE);
4130 x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
4133 x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
4134 x86_widen_reg (s->code, treg, treg, FALSE, FALSE);
4137 g_assert_not_reached ();
4140 if (treg != X86_EAX)
4141 x86_pop_reg (s->code, X86_EAX);
4144 freg: CONV_R8 (freg) {
4148 freg: CONV_R4 (freg) {
4149 /* fixme: nothing to do ??*/
4152 freg: CONV_R8 (LDIND_I4 (ADDR_G)) {
4153 x86_fild (s->code, tree->left->left->data.p, FALSE);
4156 freg: CONV_R4 (reg) {
4157 x86_push_reg (s->code, tree->left->reg1);
4158 x86_fild_membase (s->code, X86_ESP, 0, FALSE);
4159 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
4162 freg: CONV_R8 (reg) {
4163 x86_push_reg (s->code, tree->left->reg1);
4164 x86_fild_membase (s->code, X86_ESP, 0, FALSE);
4165 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
4168 freg: CONV_R_UN (reg) {
4169 x86_push_imm (s->code, 0);
4170 x86_push_reg (s->code, tree->left->reg1);
4171 x86_fild_membase (s->code, X86_ESP, 0, TRUE);
4172 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
4175 freg: CONV_R_UN (lreg) {
4176 static guint8 mn[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x40 };
4179 /* load 64bit integer to FP stack */
4180 x86_push_imm (s->code, 0);
4181 x86_push_reg (s->code, tree->left->reg2);
4182 x86_push_reg (s->code, tree->left->reg1);
4183 x86_fild_membase (s->code, X86_ESP, 0, TRUE);
4184 /* store as 80bit FP value */
4185 x86_fst80_membase (s->code, X86_ESP, 0);
4187 /* test if lreg is negative */
4188 x86_test_reg_reg (s->code, tree->left->reg2, tree->left->reg2);
4189 br [0] = s->code; x86_branch8 (s->code, X86_CC_GEZ, 0, TRUE);
4191 /* add correction constant mn */
4192 x86_fld80_mem (s->code, mn);
4193 x86_fld80_membase (s->code, X86_ESP, 0);
4194 x86_fp_op_reg (s->code, X86_FADD, 1, TRUE);
4195 x86_fst80_membase (s->code, X86_ESP, 0);
4196 //x86_breakpoint (s->code);
4197 x86_patch (br [0], s->code);
4199 x86_fld80_membase (s->code, X86_ESP, 0);
4200 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
4203 freg: CONV_R4 (lreg) {
4204 x86_push_reg (s->code, tree->left->reg2);
4205 x86_push_reg (s->code, tree->left->reg1);
4206 x86_fild_membase (s->code, X86_ESP, 0, TRUE);
4207 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
4210 freg: CONV_R8 (lreg) {
4211 x86_push_reg (s->code, tree->left->reg2);
4212 x86_push_reg (s->code, tree->left->reg1);
4213 x86_fild_membase (s->code, X86_ESP, 0, TRUE);
4214 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 8);
4218 float f = *(float *)tree->data.p;
4225 x86_fld (s->code, tree->data.p, FALSE);
4229 double d = *(double *)tree->data.p;
4236 x86_fld (s->code, tree->data.p, TRUE);
4239 freg: LDIND_R4 (addr) {
4241 switch (tree->left->data.ainfo.amode) {
4244 x86_fld (s->code, tree->left->data.ainfo.offset, FALSE);
4248 x86_fld_membase (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset, FALSE);
4251 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, X86_NOBASEREG,
4252 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
4253 tree->left->data.ainfo.shift);
4254 x86_fld_membase (s->code, tree->left->data.ainfo.indexreg, 0, FALSE);
4257 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, tree->left->data.ainfo.basereg,
4258 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
4259 tree->left->data.ainfo.shift);
4260 x86_fld_membase (s->code, tree->left->data.ainfo.indexreg, 0, FALSE);
4265 freg: LDIND_R8 (addr) {
4267 switch (tree->left->data.ainfo.amode) {
4270 x86_fld (s->code, tree->left->data.ainfo.offset, TRUE);
4274 x86_fld_membase (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset, TRUE);
4277 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, X86_NOBASEREG,
4278 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
4279 tree->left->data.ainfo.shift);
4280 x86_fld_membase (s->code, tree->left->data.ainfo.indexreg, 0, TRUE);
4283 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, tree->left->data.ainfo.basereg,
4284 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
4285 tree->left->data.ainfo.shift);
4286 x86_fld_membase (s->code, tree->left->data.ainfo.indexreg, 0, TRUE);
4292 freg: ADD (freg, freg) {
4293 x86_fp_op_reg (s->code, X86_FADD, 1, TRUE);
4296 freg: SUB (freg, freg) {
4297 x86_fp_op_reg (s->code, X86_FSUB, 1, TRUE);
4300 freg: MUL (freg, freg) {
4301 x86_fp_op_reg (s->code, X86_FMUL, 1, TRUE);
4304 freg: DIV (freg, freg) {
4305 x86_fp_op_reg (s->code, X86_FDIV, 1, TRUE);
4308 freg: CKFINITE (freg) {
4309 x86_push_reg (s->code, X86_EAX);
4311 x86_fnstsw (s->code);
4312 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4100);
4313 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
4314 x86_pop_reg (s->code, X86_EAX);
4315 EMIT_COND_SYSTEM_EXCEPTION (X86_CC_NE, FALSE, "ArithmeticException");
4318 freg: REM (freg, freg) {
4321 /* we need to exchange ST(0) with ST(1) */
4322 x86_fxch (s->code, 1);
4324 /* this requires a loop, because fprem1 somtimes
4325 * returns a partial remainder */
4327 x86_fprem1 (s->code);
4328 x86_fnstsw (s->code);
4329 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x0400);
4331 x86_branch8 (s->code, X86_CC_NE, l1 - l2, FALSE);
4334 x86_fstp (s->code, 1);
4343 stmt: STIND_R4 (addr, freg) {
4345 switch (tree->left->data.ainfo.amode) {
4348 x86_fst (s->code, tree->left->data.ainfo.offset, FALSE, TRUE);
4352 x86_fst_membase (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
4356 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, X86_NOBASEREG,
4357 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
4358 tree->left->data.ainfo.shift);
4359 x86_fst_membase (s->code, tree->left->data.ainfo.indexreg, 0, FALSE, TRUE);
4362 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, tree->left->data.ainfo.basereg,
4363 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
4364 tree->left->data.ainfo.shift);
4365 x86_fst_membase (s->code, tree->left->data.ainfo.indexreg, 0, FALSE, TRUE);
4370 stmt: STIND_R8 (addr, freg) {
4372 switch (tree->left->data.ainfo.amode) {
4375 x86_fst (s->code, tree->left->data.ainfo.offset, TRUE, TRUE);
4379 x86_fst_membase (s->code, tree->left->data.ainfo.basereg, tree->left->data.ainfo.offset,
4383 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, X86_NOBASEREG,
4384 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
4385 tree->left->data.ainfo.shift);
4386 x86_fst_membase (s->code, tree->left->data.ainfo.indexreg, 0, TRUE, TRUE);
4389 x86_lea_memindex (s->code, tree->left->data.ainfo.indexreg, tree->left->data.ainfo.basereg,
4390 tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
4391 tree->left->data.ainfo.shift);
4392 x86_fst_membase (s->code, tree->left->data.ainfo.indexreg, 0, TRUE, TRUE);
4397 stmt: REMOTE_STIND_R4 (reg, freg) {
4400 int lreg = tree->left->reg1;
4406 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
4407 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
4408 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
4410 /* this is a transparent proxy - remote the call */
4412 /* save value to stack */
4413 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
4414 x86_fst_membase (s->code, X86_ESP, 0, FALSE, TRUE);
4416 x86_push_reg (s->code, X86_ESP);
4417 x86_push_imm (s->code, tree->data.fi.field);
4418 x86_push_imm (s->code, tree->data.fi.klass);
4419 x86_push_reg (s->code, lreg);
4420 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
4421 x86_call_code (s->code, 0);
4422 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 20);
4424 br [1] = s->code; x86_jump8 (s->code, 0);
4426 x86_patch (br [0], s->code);
4427 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
4428 tree->data.fi.field->offset;
4429 x86_fst_membase (s->code, lreg, offset, FALSE, TRUE);
4431 x86_patch (br [1], s->code);
4434 stmt: REMOTE_STIND_R8 (reg, freg) {
4437 int lreg = tree->left->reg1;
4443 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
4444 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
4445 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
4447 /* this is a transparent proxy - remote the call */
4449 /* save value to stack */
4450 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
4451 x86_fst_membase (s->code, X86_ESP, 0, TRUE, TRUE);
4453 x86_push_reg (s->code, X86_ESP);
4454 x86_push_imm (s->code, tree->data.fi.field);
4455 x86_push_imm (s->code, tree->data.fi.klass);
4456 x86_push_reg (s->code, lreg);
4457 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
4458 x86_call_code (s->code, 0);
4459 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 24);
4461 br [1] = s->code; x86_jump8 (s->code, 0);
4463 x86_patch (br [0], s->code);
4464 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
4465 tree->data.fi.field->offset;
4466 x86_fst_membase (s->code, lreg, offset, TRUE, TRUE);
4468 x86_patch (br [1], s->code);
4471 stmt: ARG_R4 (freg) {
4472 int pad = tree->data.arg_info.pad;
4474 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4 + pad);
4475 x86_fst_membase (s->code, X86_ESP, 0, FALSE, TRUE);
4478 stmt: ARG_R8 (freg) {
4479 int pad = tree->data.arg_info.pad;
4481 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8 + pad);
4482 x86_fst_membase (s->code, X86_ESP, 0, TRUE, TRUE);
4485 # fixme: we need to implement unordered and ordered compares
4487 stmt: CBRANCH (COMPARE (freg, freg)) {
4489 x86_fcompp (s->code);
4490 x86_fnstsw (s->code);
4491 x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
4493 switch (tree->data.bi.cond) {
4495 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
4496 x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
4499 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
4500 x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
4503 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
4504 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
4505 x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
4508 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
4509 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
4510 x86_branch32 (s->code, X86_CC_EQ, 0, FALSE);
4513 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
4514 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
4515 x86_branch32 (s->code, X86_CC_EQ, 0, TRUE);
4518 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
4519 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
4520 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
4523 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
4524 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
4527 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
4528 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
4531 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
4532 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
4533 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
4536 x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
4537 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_BB, tree->data.bi.target);
4538 x86_branch32 (s->code, X86_CC_NE, 0, FALSE);
4541 g_assert_not_reached ();
4545 freg: CALL_R8 (this, reg) {
4547 int lreg = tree->left->reg1;
4548 int rreg = tree->right->reg1;
4550 if (lreg == treg || rreg == treg)
4552 if (lreg == treg || rreg == treg)
4554 if (lreg == treg || rreg == treg)
4555 mono_assert_not_reached ();
4559 x86_call_reg (s->code, rreg);
4564 freg: CALL_R8 (this, ADDR_G) {
4565 int lreg = tree->left->reg1;
4573 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->right->data.p);
4574 x86_call_code (s->code, 0);
4579 freg: CALL_R8 (this, INTF_ADDR) {
4580 int lreg = tree->left->reg1;
4588 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
4589 x86_mov_reg_membase (s->code, lreg, lreg,
4590 G_STRUCT_OFFSET (MonoVTable, interface_offsets), 4);
4591 x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
4592 x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
4597 freg: CALL_R8 (this, VFUNC_ADDR) {
4598 int lreg = tree->left->reg1;
4606 x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
4607 x86_call_virtual (s->code, lreg,
4608 G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
4614 if (!tree->last_instr) {
4615 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_EPILOG, NULL);
4616 x86_jump32 (s->code, 0);
4629 x86_fsqrt (s->code);
4632 # support for value types
4634 reg: LDIND_OBJ (reg) {
4635 if (tree->left->reg1 != tree->reg1)
4636 x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
4639 stmt: STIND_OBJ (reg, reg) {
4640 mono_assert (tree->data.i > 0);
4642 x86_push_imm (s->code, tree->data.i);
4643 x86_push_reg (s->code, tree->right->reg1);
4644 x86_push_reg (s->code, tree->left->reg1);
4645 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, MEMCOPY);
4646 x86_call_code (s->code, 0);
4647 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
4650 stmt: REMOTE_STIND_OBJ (reg, reg) {
4653 int lreg = tree->left->reg1;
4654 int rreg = tree->right->reg1;
4663 x86_mov_reg_membase (s->code, treg, lreg, 0, 4);
4664 x86_alu_membase_imm (s->code, X86_CMP, treg, 0, ((int)mono_defaults.transparent_proxy_class));
4665 br [0] = s->code; x86_branch8 (s->code, X86_CC_NE, 0, FALSE);
4667 /* this is a transparent proxy - remote the call */
4669 x86_push_reg (s->code, rreg);
4670 x86_push_imm (s->code, tree->data.fi.field);
4671 x86_push_imm (s->code, tree->data.fi.klass);
4672 x86_push_reg (s->code, lreg);
4673 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, mono_store_remote_field);
4674 x86_call_code (s->code, 0);
4675 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 16);
4677 br [1] = s->code; x86_jump8 (s->code, 0);
4679 x86_patch (br [0], s->code);
4681 offset = tree->data.fi.klass->valuetype ? tree->data.fi.field->offset - sizeof (MonoObject) :
4682 tree->data.fi.field->offset;
4684 size = mono_class_value_size (tree->data.fi.field->type->data.klass, NULL);
4685 x86_push_imm (s->code, size);
4686 x86_push_reg (s->code, tree->right->reg1);
4687 x86_alu_reg_imm (s->code, X86_ADD, tree->left->reg1, offset);
4688 x86_push_reg (s->code, tree->left->reg1);
4689 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, MEMCOPY);
4690 x86_call_code (s->code, 0);
4691 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
4693 x86_patch (br [1], s->code);
4696 stmt: ARG_OBJ (CONST_I4) {
4697 int pad = tree->data.arg_info.pad;
4700 x86_push_imm (s->code, tree->left->data.i);
4703 stmt: ARG_OBJ (reg) {
4704 int size = tree->data.arg_info.size;
4705 int pad = tree->data.arg_info.pad;
4713 /* reserve space for the argument */
4714 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);
4716 x86_push_imm (s->code, size);
4717 x86_push_reg (s->code, tree->left->reg1);
4718 x86_lea_membase (s->code, X86_EAX, X86_ESP, 2*4);
4719 x86_push_reg (s->code, X86_EAX);
4721 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, MEMCOPY);
4722 x86_call_code (s->code, 0);
4723 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
4726 stmt: RET_OBJ (reg) {
4727 int size = tree->data.i;
4729 x86_push_imm (s->code, size);
4730 x86_push_reg (s->code, tree->left->reg1);
4731 x86_push_membase (s->code, X86_EBP, 8);
4733 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, MEMCOPY);
4734 x86_call_code (s->code, 0);
4736 x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
4738 if (!tree->last_instr) {
4739 mono_add_jump_info (s, s->code, MONO_JUMP_INFO_EPILOG, NULL);
4740 x86_jump32 (s->code, 0);
4749 mono_llmult (gint64 a, gint64 b)
4755 mono_llmult_ovf_un (gpointer *exc, guint32 al, guint32 ah, guint32 bl, guint32 bh)
4759 // fixme: this is incredible slow
4762 goto raise_exception;
4764 res = (guint64)al * (guint64)bl;
4766 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
4768 if (t1 > 0xffffffff)
4769 goto raise_exception;
4771 res += ((guint64)t1) << 32;
4777 *exc = mono_get_exception_overflow ();
4782 mono_llmult_ovf (gpointer *exc, guint32 al, gint32 ah, guint32 bl, gint32 bh)
4786 // fixme: check for overflow
4788 res = (gint64)al * (gint64)bl;
4790 t1 = (gint64)ah * bl + al * (gint64)bh;
4792 res += ((gint64)t1) << 32;
4798 *exc = mono_get_exception_overflow ();
4804 mono_lldiv (gint64 a, gint64 b)
4810 mono_llrem (gint64 a, gint64 b)
4816 mono_lldiv_un (guint64 a, guint64 b)
4822 mono_llrem_un (guint64 a, guint64 b)
4828 mono_array_new_wrapper (MonoClass *eclass, guint32 n)
4830 MonoDomain *domain = mono_domain_get ();
4832 return mono_array_new (domain, eclass, n);
4836 mono_object_new_wrapper (MonoClass *klass)
4838 MonoDomain *domain = mono_domain_get ();
4840 return mono_object_new (domain, klass);
4844 mono_ldstr_wrapper (MonoImage *image, guint32 ind)
4846 MonoDomain *domain = mono_domain_get ();
4848 return mono_ldstr (domain, image, ind);
4852 mono_ldsflda (MonoClass *klass, int offset)
4854 MonoDomain *domain = mono_domain_get ();
4858 vt = mono_class_vtable (domain, klass);
4859 addr = (char*)(vt->data) + offset;
4865 debug_memcopy (void *dest, const void *src, size_t n)
4869 printf ("MEMCPY(%p to %p [%d]) ", src, dest, n);
4871 for (i = 0; i < l; i++)
4872 printf ("%02x ", *((guint8 *)src + i));
4875 return memcpy (dest, src, n);
4878 void mono_emit_fast_iconv (MBCGEN_TYPE* s, MBTREE_TYPE* tree)
4881 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 12);
4882 x86_fist_membase (s->code, X86_ESP, 8, TRUE); // rounded value
4883 x86_fst_membase (s->code, X86_ESP, 0, FALSE, FALSE); // float value
4884 x86_fp_int_op_membase (s->code, X86_FSUB, X86_ESP, 8, TRUE);
4885 x86_fst_membase (s->code, X86_ESP, 4, FALSE, TRUE); // diff
4887 x86_pop_reg (s->code, tree->reg1); // float value
4888 x86_test_reg_reg (s->code, tree->reg1, tree->reg1);
4889 br[0] = s->code; x86_branch8 (s->code, X86_CC_S, 0, TRUE);
4891 x86_pop_reg (s->code, tree->reg1); // diff
4892 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->reg1);
4893 x86_pop_reg (s->code, tree->reg1); // rounded value
4894 x86_alu_reg_imm (s->code, X86_SBB, tree->reg1, 0);
4895 br[1] = s->code; x86_jump8 (s->code, 0);
4898 x86_patch (br[0], s->code);
4900 x86_pop_reg (s->code, tree->reg1); // diff
4901 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->reg1);
4902 x86_pop_reg (s->code, tree->reg1); // rounded value
4903 br[2] = s->code; x86_branch8 (s->code, X86_CC_Z, 0, FALSE);
4904 x86_alu_reg_imm (s->code, X86_SBB, tree->reg1, -1);
4905 x86_patch (br[1], s->code);
4906 x86_patch (br[2], s->code);
4909 void mono_emit_fast_iconv_i8 (MBCGEN_TYPE* s, MBTREE_TYPE* tree)
4912 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 16);
4913 x86_fld_reg (s->code, 0);
4914 x86_fist_pop_membase (s->code, X86_ESP, 8, TRUE); // rounded value (qword)
4915 x86_fst_membase (s->code, X86_ESP, 0, FALSE, FALSE); // float value
4916 x86_fild_membase (s->code, X86_ESP, 8, TRUE);
4917 x86_fp_op_reg (s->code, X86_FSUB, 1, TRUE); // diff
4918 x86_fst_membase (s->code, X86_ESP, 4, FALSE, TRUE); // diff
4920 x86_pop_reg (s->code, tree->reg1); // float value
4921 x86_test_reg_reg (s->code, tree->reg1, tree->reg1);
4922 br[0] = s->code; x86_branch8 (s->code, X86_CC_S, 0, TRUE);
4924 x86_pop_reg (s->code, tree->reg1); // diff
4925 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->reg1);
4926 x86_pop_reg (s->code, tree->reg1); // rounded value
4927 x86_pop_reg (s->code, tree->reg2);
4928 x86_alu_reg_imm (s->code, X86_SBB, tree->reg1, 0);
4929 x86_alu_reg_imm (s->code, X86_SBB, tree->reg2, 0);
4930 br[1] = s->code; x86_jump8 (s->code, 0);
4933 x86_patch (br[0], s->code);
4935 x86_pop_reg (s->code, tree->reg1); // diff
4936 x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->reg1);
4937 x86_pop_reg (s->code, tree->reg1); // rounded value
4938 x86_pop_reg (s->code, tree->reg2);
4939 br[2] = s->code; x86_branch8 (s->code, X86_CC_Z, 0, FALSE);
4940 x86_alu_reg_imm (s->code, X86_SBB, tree->reg1, -1);
4941 x86_alu_reg_imm (s->code, X86_SBB, tree->reg2, -1);
4942 x86_patch (br[1], s->code);
4943 x86_patch (br[2], s->code);
4946 void mono_emit_stack_alloc (MBCGEN_TYPE* s, MBTREE_TYPE* tree)
4948 #ifdef PLATFORM_WIN32
4954 * If requested stack size is larger than one page,
4955 * perform stack-touch operation
4956 * (see comments in mono_emit_stack_alloc_const below).
4958 x86_test_reg_imm (s->code, tree->left->reg1, ~0xFFF);
4959 br[0] = s->code; x86_branch8 (s->code, X86_CC_Z, 0, FALSE);
4961 sreg = tree->left->reg1;
4963 br[2] = s->code; /* loop */
4964 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 0x1000);
4965 x86_test_membase_reg (s->code, X86_ESP, 0, X86_ESP);
4966 x86_alu_reg_imm (s->code, X86_SUB, sreg, 0x1000);
4967 x86_alu_reg_imm (s->code, X86_CMP, sreg, 0x1000);
4968 br[3] = s->code; x86_branch8 (s->code, X86_CC_AE, 0, FALSE);
4969 x86_patch (br[3], br[2]);
4970 x86_test_reg_reg (s->code, sreg, sreg);
4971 br[4] = s->code; x86_branch8 (s->code, X86_CC_Z, 0, FALSE);
4972 x86_alu_reg_reg (s->code, X86_SUB, X86_ESP, sreg);
4974 br[1] = s->code; x86_jump8 (s->code, 0);
4976 x86_patch (br[0], s->code);
4977 x86_alu_reg_reg (s->code, X86_SUB, X86_ESP, tree->left->reg1);
4978 x86_patch (br[1], s->code);
4979 x86_patch (br[4], s->code);
4980 #else /* PLATFORM_WIN32 */
4981 x86_alu_reg_reg (s->code, X86_SUB, X86_ESP, tree->left->reg1);
4985 void mono_emit_stack_alloc_const (MBCGEN_TYPE* s, MBTREE_TYPE* tree, int size)
4987 #ifdef PLATFORM_WIN32
4993 * Generate stack probe code.
4994 * Under Windows, it is necessary to allocate one page at a time,
4995 * "touching" stack after each successful sub-allocation. This is
4996 * because of the way stack growth is implemented - there is a
4997 * guard page before the lowest stack page that is currently commited.
4998 * Stack normally grows sequentially so OS traps access to the
4999 * guard page and commits more pages when needed.
5001 npages = ((unsigned) size) >> 12;
5003 if (tree->reg1 != X86_EAX && tree->left->reg1 != X86_EAX) {
5004 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 0x1000);
5005 x86_test_membase_reg (s->code, X86_ESP, 0, X86_ESP);
5006 x86_mov_membase_reg (s->code, X86_ESP, 0x1000 - 4, X86_EAX, 4); /* save EAX */
5007 x86_mov_reg_imm (s->code, X86_EAX, npages - 1);
5009 x86_mov_reg_imm (s->code, X86_EAX, npages);
5011 br[0] = s->code; /* loop */
5012 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 0x1000);
5013 x86_test_membase_reg (s->code, X86_ESP, 0, X86_ESP);
5014 x86_dec_reg (s->code, X86_EAX);
5015 br[1] = s->code; x86_branch8 (s->code, X86_CC_NZ, 0, TRUE);
5016 x86_patch (br[1], br[0]);
5017 if (tree->reg1 != X86_EAX && tree->left->reg1 != X86_EAX)
5018 x86_mov_reg_membase (s->code, X86_EAX, X86_ESP, (npages * 0x1000) - 4, 4); /* restore EAX */
5020 /* generate unrolled code for relatively small allocs */
5021 for (i = npages; --i >= 0;) {
5022 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 0x1000);
5023 x86_test_membase_reg (s->code, X86_ESP, 0, X86_ESP);
5028 if (size & 0xFFF) x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, -(size & 0xFFF));
5029 #else /* PLATFORM_WIN32 */
5030 x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, size);
5035 mono_ldvirtftn (MonoObject *this, int slot)
5040 gboolean is_proxy = FALSE;
5043 if ((class = this->vtable->klass) == mono_defaults.transparent_proxy_class) {
5044 class = ((MonoTransparentProxy *)this)->klass;
5049 g_assert (slot <= class->vtable_size);
5051 m = class->vtable [slot];
5054 return mono_jit_create_remoting_trampoline (m);
5056 EnterCriticalSection (metadata_section);
5057 addr = mono_compile_method (m);
5058 LeaveCriticalSection (metadata_section);
5064 mono_ldintftn (MonoObject *this, int slot)
5069 gboolean is_proxy = FALSE;
5072 if ((class = this->vtable->klass) == mono_defaults.transparent_proxy_class) {
5073 class = ((MonoTransparentProxy *)this)->klass;
5077 g_assert (slot < class->interface_count);
5079 slot = class->interface_offsets [slot];
5081 m = class->vtable [slot];
5084 return mono_jit_create_remoting_trampoline (m);
5086 EnterCriticalSection (metadata_section);
5087 addr = mono_compile_method (m);
5088 LeaveCriticalSection (metadata_section);
5093 gpointer mono_ldftn (MonoMethod *method)
5097 EnterCriticalSection (metadata_section);
5098 addr = mono_compile_method (method);
5099 LeaveCriticalSection (metadata_section);