2 * PLEASE NOTE: This is a research prototype.
5 * interp.c: Interpreter for CIL byte codes
8 * Paolo Molaro (lupus@ximian.com)
9 * Miguel de Icaza (miguel@ximian.com)
11 * (C) 2001 Ximian, Inc.
22 # define alloca __builtin_alloca
27 /* trim excessive headers */
28 #include <mono/metadata/image.h>
29 #include <mono/metadata/assembly.h>
30 #include <mono/metadata/cil-coff.h>
31 #include <mono/metadata/endian.h>
32 #include <mono/metadata/tabledefs.h>
33 #include <mono/metadata/blob.h>
34 #include <mono/metadata/tokentype.h>
35 #include <mono/cli/cli.h>
38 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
42 #include "mono/cil/opcode.def"
47 /* this needs to be metadata,token indexed, not only token */
48 static GHashTable * method_cache = 0;
50 /* FIXME: check in configure */
51 typedef gint32 nati_t;
53 #define GET_NATI(sp) ((guint32)(sp).data.i)
57 #define CSIZE(x) (sizeof (x) / 4)
60 ves_real_abort (int line, MonoImage *image, MonoMethod *mh,
61 const unsigned char *ip, stackval *stack, stackval *sp)
63 cli_image_info_t *iinfo = image->image_info;
64 metadata_t *m = &iinfo->cli_metadata;
65 const char *name = mono_metadata_string_heap (m, mh->name_idx);
67 fprintf (stderr, "Execution aborted in method: %s\n", name);
68 fprintf (stderr, "Line=%d IP=0x%04x, Aborted execution\n", line,
69 ip-(unsigned char *)mh->header->code);
70 g_print ("0x%04x %02x\n",
71 ip-(unsigned char*)mh->header->code, *ip);
73 printf ("\t[%d] %d 0x%08x %0.5f\n", sp-stack, sp[-1].type, sp[-1].data.i, sp[-1].data.f);
76 #define ves_abort() ves_real_abort(__LINE__, image, mh, ip, stack, sp)
80 * @image: image where the object is being referenced
81 * @token: method token to invoke
83 * This routine creates a new object based on the class where the
87 newobj (MonoImage *image, guint32 token)
89 cli_image_info_t *iinfo = image->image_info;
90 metadata_t *m = &iinfo->cli_metadata;
92 switch (mono_metadata_token_code (token)){
93 case TOKEN_TYPE_METHOD_DEF:
94 g_error ("TOKEN_TYPE_METHOD_DEF not supported in newobj yet");
97 case TOKEN_TYPE_MEMBER_REF: {
98 guint32 member_cols [3];
99 guint32 mpr_token, table, idx;
101 mono_metadata_decode_row (
102 &m->tables [META_TABLE_MEMBERREF],
103 mono_metadata_token_index (token) - 1,
104 member_cols, CSIZE (member_cols));
105 mpr_token = member_cols [0];
106 table = mpr_token & 7;
107 idx = mpr_token >> 3;
110 case 0: /* TypeDef */
111 return mono_object_new (image, TOKEN_TYPE_TYPE_DEF | idx);
113 case 1: /* TypeRef */
114 return mono_object_new (image, TOKEN_TYPE_TYPE_REF | idx);
116 case 2: /* ModuleRef */
117 g_error ("Unhandled: ModuleRef");
119 case 3: /* MethodDef */
120 g_error ("Unhandled: MethodDef");
122 case 4: /* TypeSpec */
123 g_error ("Unhandled: TypeSepc");
136 * Need to optimize ALU ops when natural int == int32
138 * Need to design how exceptions are supposed to work...
140 * IDEA: if we maintain a stack of ip, sp to be checked
141 * in the return opcode, we could inline simple methods that don't
142 * use the stack or local variables....
144 * The {,.S} versions of many opcodes can/should be merged to reduce code
147 * -fomit-frame-pointer gives about 2% speedup.
150 ves_exec_method (MonoImage *image, MonoMethod *mh, stackval *args)
153 * with alloca we get the expected huge performance gain
154 * stackval *stack = g_new0(stackval, mh->max_stack);
156 stackval *stack = alloca (sizeof (stackval) * mh->header->max_stack);
157 register const unsigned char *ip = mh->header->code;
158 register stackval *sp = stack;
159 /* FIXME: remove this hack */
160 static int fake_field = 42;
164 if (mh->header->num_locals)
165 locals = alloca (sizeof (stackval) * mh->header->num_locals);
168 * using while (ip < end) may result in a 15% performance drop,
169 * but it may be useful for debug
175 g_print ("0x%04x %02x\n", ip-(unsigned char*)mh->header->code, *ip);
177 printf ("\t[%d] %d 0x%08x %0.5f\n", sp-stack, sp[-1].type,
178 sp[-1].data.i, sp[-1].data.f);
188 G_BREAKPOINT (); /* this is not portable... */
194 *sp = args [(*ip)-CEE_LDARG_0];
202 *sp = locals [(*ip)-CEE_LDLOC_0];
211 locals [(*ip)-CEE_STLOC_0] = *sp;
223 sp->data.p = &(args [*ip]);
227 CASE (CEE_STARG_S) ves_abort(); BREAK;
234 CASE (CEE_LDLOCA_S) ves_abort(); BREAK;
263 sp->data.i = (*ip) - CEE_LDC_I4_0;
270 sp->data.i = *ip; /* FIXME: signed? */
277 sp->data.i = read32 (ip);
284 sp->data.i = read64 (ip);
290 sp->type = VAL_DOUBLE;
291 /* FIXME: ENOENDIAN */
292 sp->data.f = *(float*)(ip);
293 ip += sizeof (float);
298 sp->type = VAL_DOUBLE;
299 /* FIXME: ENOENDIAN */
300 sp->data.f = *(double*) (ip);
301 ip += sizeof (double);
304 CASE (CEE_UNUSED99) ves_abort (); BREAK;
314 CASE (CEE_JMP) ves_abort(); BREAK;
322 if (!(cmh = g_hash_table_lookup (method_cache, GINT_TO_POINTER (token)))) {
323 cmh = mono_get_method (image, token);
324 g_hash_table_insert (method_cache, GINT_TO_POINTER (token), cmh);
327 /* decrement by the actual number of args */
328 sp -= cmh->signature->param_count;
329 g_assert (cmh->signature->call_convention == MONO_CALL_DEFAULT);
331 /* we need to truncate according to the type of args ... */
332 ves_exec_method (image, cmh, sp);
334 /* need to handle typedbyref ... */
335 if (cmh->signature->ret->type)
339 CASE (CEE_CALLI) ves_abort(); BREAK;
344 g_warning ("more values on stack: %d", sp-stack);
346 /*if (sp->type == VAL_DOUBLE)
347 g_print("%.9f\n", sp->data.f);*/
352 ip += (signed char) *ip;
355 CASE (CEE_BRFALSE_S) {
360 case VAL_I32: result = sp->data.i == 0; break;
361 case VAL_I64: result = sp->data.l == 0; break;
362 case VAL_DOUBLE: result = sp->data.f ? 0: 1; break;
363 default: result = sp->data.p == NULL; break;
366 ip += (signed char)*ip;
370 CASE (CEE_BRTRUE_S) {
375 case VAL_I32: result = sp->data.i != 0; break;
376 case VAL_I64: result = sp->data.l != 0; break;
377 case VAL_DOUBLE: result = sp->data.f ? 1 : 0; break;
378 default: result = sp->data.p != NULL; break;
381 ip += (signed char)*ip;
389 if (sp->type == VAL_I32)
390 result = sp [0].data.i == GET_NATI (sp [1]);
391 else if (sp->type == VAL_I64)
392 result = sp [0].data.l == sp [1].data.l;
393 else if (sp->type == VAL_DOUBLE)
394 result = sp [0].data.f == sp [1].data.f;
396 result = GET_NATI (sp [0]) == GET_NATI (sp [1]);
398 ip += (signed char)*ip;
406 if (sp->type == VAL_I32)
407 result = sp [0].data.i >= GET_NATI (sp [1]);
408 else if (sp->type == VAL_I64)
409 result = sp [0].data.l >= sp [1].data.l;
410 else if (sp->type == VAL_DOUBLE)
411 result = sp [0].data.f >= sp [1].data.f;
413 result = GET_NATI (sp [0]) >= GET_NATI (sp [1]);
415 ip += (signed char)*ip;
423 if (sp->type == VAL_I32)
424 result = sp [0].data.i > GET_NATI (sp [1]);
425 else if (sp->type == VAL_I64)
426 result = sp [0].data.l > sp [1].data.l;
427 else if (sp->type == VAL_DOUBLE)
428 result = sp [0].data.f > sp [1].data.f;
430 result = GET_NATI (sp [0]) > GET_NATI (sp [1]);
432 ip += (signed char)*ip;
440 if (sp->type == VAL_I32)
441 result = sp[0].data.i < GET_NATI(sp[1]);
442 else if (sp->type == VAL_I64)
443 result = sp[0].data.l < sp[1].data.l;
444 else if (sp->type == VAL_DOUBLE)
445 result = sp[0].data.f < sp[1].data.f;
447 result = GET_NATI(sp[0]) < GET_NATI(sp[1]);
449 ip += (signed char)*ip;
458 if (sp->type == VAL_I32)
459 result = sp [0].data.i <= GET_NATI (sp [1]);
460 else if (sp->type == VAL_I64)
461 result = sp [0].data.l <= sp [1].data.l;
462 else if (sp->type == VAL_DOUBLE)
463 result = sp [0].data.f <= sp [1].data.f;
466 * FIXME: here and in other places GET_NATI on the left side
467 * _will_ be wrong when we change the macro to work on 64 buts
470 result = GET_NATI (sp [0]) <= GET_NATI (sp [1]);
473 ip += (signed char)*ip;
477 CASE (CEE_BNE_UN_S) ves_abort(); BREAK;
478 CASE (CEE_BGE_UN_S) ves_abort(); BREAK;
479 CASE (CEE_BGT_UN_S) ves_abort(); BREAK;
480 CASE (CEE_BLE_UN_S) ves_abort(); BREAK;
481 CASE (CEE_BLT_UN_S) ves_abort(); BREAK;
482 CASE (CEE_BR) ves_abort(); BREAK;
483 CASE (CEE_BRFALSE) ves_abort(); BREAK;
484 CASE (CEE_BRTRUE) ves_abort(); BREAK;
485 CASE (CEE_BEQ) ves_abort(); BREAK;
486 CASE (CEE_BGE) ves_abort(); BREAK;
487 CASE (CEE_BGT) ves_abort(); BREAK;
488 CASE (CEE_BLE) ves_abort(); BREAK;
489 CASE (CEE_BLT) ves_abort(); BREAK;
490 CASE (CEE_BNE_UN) ves_abort(); BREAK;
491 CASE (CEE_BGE_UN) ves_abort(); BREAK;
492 CASE (CEE_BGT_UN) ves_abort(); BREAK;
493 CASE (CEE_BLE_UN) ves_abort(); BREAK;
494 CASE (CEE_BLT_UN) ves_abort(); BREAK;
497 const unsigned char *st;
501 st = ip + sizeof (gint32) * n;
503 if ((guint32)sp->data.i < n) {
505 ip += sizeof (gint32) * (guint32)sp->data.i;
506 offset = read32 (ip);
513 CASE (CEE_LDIND_I1) ves_abort(); BREAK;
514 CASE (CEE_LDIND_U1) ves_abort(); BREAK;
515 CASE (CEE_LDIND_I2) ves_abort(); BREAK;
516 CASE (CEE_LDIND_U2) ves_abort(); BREAK;
517 CASE (CEE_LDIND_I4) ves_abort(); BREAK;
518 CASE (CEE_LDIND_U4) ves_abort(); BREAK;
519 CASE (CEE_LDIND_I8) ves_abort(); BREAK;
520 CASE (CEE_LDIND_I) ves_abort(); BREAK;
521 CASE (CEE_LDIND_R4) ves_abort(); BREAK;
522 CASE (CEE_LDIND_R8) ves_abort(); BREAK;
523 CASE (CEE_LDIND_REF) ves_abort(); BREAK;
524 CASE (CEE_STIND_REF) ves_abort(); BREAK;
525 CASE (CEE_STIND_I1) ves_abort(); BREAK;
526 CASE (CEE_STIND_I2) ves_abort(); BREAK;
527 CASE (CEE_STIND_I4) ves_abort(); BREAK;
528 CASE (CEE_STIND_I8) ves_abort(); BREAK;
529 CASE (CEE_STIND_R4) ves_abort(); BREAK;
530 CASE (CEE_STIND_R8) ves_abort(); BREAK;
534 /* should probably consider the pointers as unsigned */
535 if (sp->type == VAL_I32)
536 sp [-1].data.i += GET_NATI (sp [0]);
537 else if (sp->type == VAL_I64)
538 sp [-1].data.l += sp [0].data.l;
539 else if (sp->type == VAL_DOUBLE)
540 sp [-1].data.f += sp [0].data.f;
542 (char*)sp [-1].data.p += GET_NATI (sp [0]);
547 /* should probably consider the pointers as unsigned */
548 if (sp->type == VAL_I32)
549 sp [-1].data.i -= GET_NATI (sp [0]);
550 else if (sp->type == VAL_I64)
551 sp [-1].data.l -= sp [0].data.l;
552 else if (sp->type == VAL_DOUBLE)
553 sp [-1].data.f -= sp [0].data.f;
555 (char*)sp [-1].data.p -= GET_NATI (sp [0]);
560 if (sp->type == VAL_I32)
561 sp [-1].data.i *= GET_NATI (sp [0]);
562 else if (sp->type == VAL_I64)
563 sp [-1].data.l *= sp [0].data.l;
564 else if (sp->type == VAL_DOUBLE)
565 sp [-1].data.f *= sp [0].data.f;
570 if (sp->type == VAL_I32)
571 sp [-1].data.i /= GET_NATI (sp [0]);
572 else if (sp->type == VAL_I64)
573 sp [-1].data.l /= sp [0].data.l;
574 else if (sp->type == VAL_DOUBLE)
575 sp [-1].data.f /= sp [0].data.f;
580 if (sp->type == VAL_I32)
581 (guint32)sp [-1].data.i /= (guint32)GET_NATI (sp [0]);
582 else if (sp->type == VAL_I64)
583 (guint64)sp [-1].data.l /= (guint64)sp [0].data.l;
584 else if (sp->type == VAL_NATI)
585 (gulong)sp [-1].data.p /= (gulong)sp [0].data.p;
590 if (sp->type == VAL_I32)
591 sp [-1].data.i %= GET_NATI (sp [0]);
592 else if (sp->type == VAL_I64)
593 sp [-1].data.l %= sp [0].data.l;
594 else if (sp->type == VAL_DOUBLE)
595 /* FIXME: what do we actually fo here? */
598 GET_NATI (sp [-1]) %= GET_NATI (sp [0]);
600 CASE (CEE_REM_UN) ves_abort(); BREAK;
604 if (sp->type == VAL_I32)
605 sp [-1].data.i &= GET_NATI (sp [0]);
606 else if (sp->type == VAL_I64)
607 sp [-1].data.l &= sp [0].data.l;
609 GET_NATI (sp [-1]) &= GET_NATI (sp [0]);
614 if (sp->type == VAL_I32)
615 sp [-1].data.i |= GET_NATI (sp [0]);
616 else if (sp->type == VAL_I64)
617 sp [-1].data.l |= sp [0].data.l;
619 GET_NATI (sp [-1]) |= GET_NATI (sp [0]);
624 if (sp->type == VAL_I32)
625 sp [-1].data.i ^= GET_NATI (sp [0]);
626 else if (sp->type == VAL_I64)
627 sp [-1].data.l ^= sp [0].data.l;
629 GET_NATI (sp [-1]) ^= GET_NATI (sp [0]);
634 if (sp->type == VAL_I32)
635 sp [-1].data.i <<= GET_NATI (sp [0]);
636 else if (sp->type == VAL_I64)
637 sp [-1].data.l <<= GET_NATI (sp [0]);
639 GET_NATI (sp [-1]) <<= GET_NATI (sp [0]);
644 if (sp->type == VAL_I32)
645 sp [-1].data.i >>= GET_NATI (sp [0]);
646 else if (sp->type == VAL_I64)
647 sp [-1].data.l >>= GET_NATI (sp [0]);
649 GET_NATI (sp [-1]) >>= GET_NATI (sp [0]);
651 CASE (CEE_SHR_UN) ves_abort(); BREAK;
654 if (sp->type == VAL_I32)
655 sp->data.i = - sp->data.i;
656 else if (sp->type == VAL_I64)
657 sp->data.l = - sp->data.l;
658 else if (sp->type == VAL_DOUBLE)
659 sp->data.f = - sp->data.f;
660 else if (sp->type == VAL_NATI)
661 sp->data.p = (gpointer)(- (nati_t)sp->data.p);
665 if (sp->type == VAL_I32)
666 sp->data.i = ~ sp->data.i;
667 else if (sp->type == VAL_I64)
668 sp->data.l = ~ sp->data.l;
669 else if (sp->type == VAL_NATI)
670 sp->data.p = (gpointer)(~ (nati_t)sp->data.p);
672 CASE (CEE_CONV_I1) ves_abort(); BREAK;
673 CASE (CEE_CONV_I2) ves_abort(); BREAK;
676 /* FIXME: handle other cases. what about sign? */
677 if (sp [-1].type == VAL_DOUBLE) {
678 sp [-1].data.i = (gint32)sp [-1].data.f;
679 sp [-1].type = VAL_I32;
684 CASE (CEE_CONV_I8) ves_abort(); BREAK;
685 CASE (CEE_CONV_R4) ves_abort(); BREAK;
688 /* FIXME: handle other cases. what about sign? */
689 if (sp [-1].type == VAL_I32) {
690 sp [-1].data.f = (double)sp [-1].data.i;
691 sp [-1].type = VAL_DOUBLE;
698 /* FIXME: handle other cases. what about sign? */
699 if (sp [-1].type == VAL_DOUBLE) {
700 sp [-1].data.i = (guint32)sp [-1].data.f;
701 sp [-1].type = VAL_I32;
706 CASE (CEE_CONV_U8) ves_abort(); BREAK;
707 CASE (CEE_CALLVIRT) ves_abort(); BREAK;
708 CASE (CEE_CPOBJ) ves_abort(); BREAK;
709 CASE (CEE_LDOBJ) ves_abort(); BREAK;
710 CASE (CEE_LDSTR) ves_abort(); BREAK;
718 o = newobj (image, token);
723 CASE (CEE_CASTCLASS) ves_abort(); BREAK;
724 CASE (CEE_ISINST) ves_abort(); BREAK;
725 CASE (CEE_CONV_R_UN) ves_abort(); BREAK;
726 CASE (CEE_UNUSED58) ves_abort(); BREAK;
727 CASE (CEE_UNUSED1) ves_abort(); BREAK;
728 CASE (CEE_UNBOX) ves_abort(); BREAK;
729 CASE (CEE_THROW) ves_abort(); BREAK;
730 CASE (CEE_LDFLD) ves_abort(); BREAK;
731 CASE (CEE_LDFLDA) ves_abort(); BREAK;
732 CASE (CEE_STFLD) ves_abort(); BREAK;
734 /* FIXME: get the real field here */
737 sp->data.i = fake_field;
740 CASE (CEE_LDSFLDA) ves_abort(); BREAK;
742 /* FIXME: get the real field here */
745 fake_field = sp->data.i;
747 CASE (CEE_STOBJ) ves_abort(); BREAK;
748 CASE (CEE_CONV_OVF_I1_UN) ves_abort(); BREAK;
749 CASE (CEE_CONV_OVF_I2_UN) ves_abort(); BREAK;
750 CASE (CEE_CONV_OVF_I4_UN) ves_abort(); BREAK;
751 CASE (CEE_CONV_OVF_I8_UN) ves_abort(); BREAK;
752 CASE (CEE_CONV_OVF_U1_UN) ves_abort(); BREAK;
753 CASE (CEE_CONV_OVF_U2_UN) ves_abort(); BREAK;
754 CASE (CEE_CONV_OVF_U4_UN) ves_abort(); BREAK;
755 CASE (CEE_CONV_OVF_U8_UN) ves_abort(); BREAK;
756 CASE (CEE_CONV_OVF_I_UN) ves_abort(); BREAK;
757 CASE (CEE_CONV_OVF_U_UN) ves_abort(); BREAK;
758 CASE (CEE_BOX) ves_abort(); BREAK;
759 CASE (CEE_NEWARR) ves_abort(); BREAK;
760 CASE (CEE_LDLEN) ves_abort(); BREAK;
761 CASE (CEE_LDELEMA) ves_abort(); BREAK;
762 CASE (CEE_LDELEM_I1) ves_abort(); BREAK;
763 CASE (CEE_LDELEM_U1) ves_abort(); BREAK;
764 CASE (CEE_LDELEM_I2) ves_abort(); BREAK;
765 CASE (CEE_LDELEM_U2) ves_abort(); BREAK;
766 CASE (CEE_LDELEM_I4) ves_abort(); BREAK;
767 CASE (CEE_LDELEM_U4) ves_abort(); BREAK;
768 CASE (CEE_LDELEM_I8) ves_abort(); BREAK;
769 CASE (CEE_LDELEM_I) ves_abort(); BREAK;
770 CASE (CEE_LDELEM_R4) ves_abort(); BREAK;
771 CASE (CEE_LDELEM_R8) ves_abort(); BREAK;
772 CASE (CEE_LDELEM_REF) ves_abort(); BREAK;
773 CASE (CEE_STELEM_I) ves_abort(); BREAK;
774 CASE (CEE_STELEM_I1) ves_abort(); BREAK;
775 CASE (CEE_STELEM_I2) ves_abort(); BREAK;
776 CASE (CEE_STELEM_I4) ves_abort(); BREAK;
777 CASE (CEE_STELEM_I8) ves_abort(); BREAK;
778 CASE (CEE_STELEM_R4) ves_abort(); BREAK;
779 CASE (CEE_STELEM_R8) ves_abort(); BREAK;
780 CASE (CEE_STELEM_REF) ves_abort(); BREAK;
796 CASE (CEE_UNUSED17) ves_abort(); BREAK;
797 CASE (CEE_CONV_OVF_I1) ves_abort(); BREAK;
798 CASE (CEE_CONV_OVF_U1) ves_abort(); BREAK;
799 CASE (CEE_CONV_OVF_I2) ves_abort(); BREAK;
800 CASE (CEE_CONV_OVF_U2) ves_abort(); BREAK;
801 CASE (CEE_CONV_OVF_I4) ves_abort(); BREAK;
802 CASE (CEE_CONV_OVF_U4) ves_abort(); BREAK;
803 CASE (CEE_CONV_OVF_I8) ves_abort(); BREAK;
804 CASE (CEE_CONV_OVF_U8) ves_abort(); BREAK;
811 CASE (CEE_UNUSED23) ves_abort(); BREAK;
812 CASE (CEE_REFANYVAL) ves_abort(); BREAK;
813 CASE (CEE_CKFINITE) ves_abort(); BREAK;
814 CASE (CEE_UNUSED24) ves_abort(); BREAK;
815 CASE (CEE_UNUSED25) ves_abort(); BREAK;
816 CASE (CEE_MKREFANY) ves_abort(); BREAK;
825 CASE (CEE_UNUSED67) ves_abort(); BREAK;
826 CASE (CEE_LDTOKEN) ves_abort(); BREAK;
827 CASE (CEE_CONV_U2) ves_abort(); BREAK;
828 CASE (CEE_CONV_U1) ves_abort(); BREAK;
829 CASE (CEE_CONV_I) ves_abort(); BREAK;
830 CASE (CEE_CONV_OVF_I) ves_abort(); BREAK;
831 CASE (CEE_CONV_OVF_U) ves_abort(); BREAK;
832 CASE (CEE_ADD_OVF) ves_abort(); BREAK;
833 CASE (CEE_ADD_OVF_UN) ves_abort(); BREAK;
834 CASE (CEE_MUL_OVF) ves_abort(); BREAK;
835 CASE (CEE_MUL_OVF_UN) ves_abort(); BREAK;
836 CASE (CEE_SUB_OVF) ves_abort(); BREAK;
837 CASE (CEE_SUB_OVF_UN) ves_abort(); BREAK;
838 CASE (CEE_ENDFINALLY) ves_abort(); BREAK;
839 CASE (CEE_LEAVE) ves_abort(); BREAK;
840 CASE (CEE_LEAVE_S) ves_abort(); BREAK;
841 CASE (CEE_STIND_I) ves_abort(); BREAK;
842 CASE (CEE_CONV_U) ves_abort(); BREAK;
865 CASE (CEE_UNUSED48) ves_abort(); BREAK;
866 CASE (CEE_PREFIX7) ves_abort(); BREAK;
867 CASE (CEE_PREFIX6) ves_abort(); BREAK;
868 CASE (CEE_PREFIX5) ves_abort(); BREAK;
869 CASE (CEE_PREFIX4) ves_abort(); BREAK;
870 CASE (CEE_PREFIX3) ves_abort(); BREAK;
871 CASE (CEE_PREFIX2) ves_abort(); BREAK;
872 CASE (CEE_PREFIXREF) ves_abort(); BREAK;
876 case CEE_ARGLIST: ves_abort(); break;
877 case CEE_CEQ: ves_abort(); break;
878 case CEE_CGT: ves_abort(); break;
879 case CEE_CGT_UN: ves_abort(); break;
880 case CEE_CLT: ves_abort(); break;
881 case CEE_CLT_UN: ves_abort(); break;
882 case CEE_LDFTN: ves_abort(); break;
883 case CEE_LDVIRTFTN: ves_abort(); break;
884 case CEE_UNUSED56: ves_abort(); break;
885 case CEE_LDARG: ves_abort(); break;
886 case CEE_LDARGA: ves_abort(); break;
887 case CEE_STARG: ves_abort(); break;
888 case CEE_LDLOC: ves_abort(); break;
889 case CEE_LDLOCA: ves_abort(); break;
890 case CEE_STLOC: ves_abort(); break;
891 case CEE_LOCALLOC: ves_abort(); break;
892 case CEE_UNUSED57: ves_abort(); break;
893 case CEE_ENDFILTER: ves_abort(); break;
894 case CEE_UNALIGNED_: ves_abort(); break;
895 case CEE_VOLATILE_: ves_abort(); break;
896 case CEE_TAIL_: ves_abort(); break;
897 case CEE_INITOBJ: ves_abort(); break;
898 case CEE_UNUSED68: ves_abort(); break;
899 case CEE_CPBLK: ves_abort(); break;
900 case CEE_INITBLK: ves_abort(); break;
901 case CEE_UNUSED69: ves_abort(); break;
902 case CEE_RETHROW: ves_abort(); break;
903 case CEE_UNUSED: ves_abort(); break;
904 case CEE_SIZEOF: ves_abort(); break;
905 case CEE_REFANYTYPE: ves_abort(); break;
912 g_error ("Unimplemented opcode: 0xFE %02x at 0x%x\n", *ip, ip-(unsigned char*)mh->header->code);
919 g_assert_not_reached ();
923 ves_exec (MonoAssembly *assembly)
925 MonoImage *image = assembly->image;
926 cli_image_info_t *iinfo;
930 iinfo = image->image_info;
932 /* we need to exec the class and object constructors... */
933 method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
935 mh = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point);
936 ves_exec_method (image, mh, &result);
937 fprintf (stderr, "result: %d\n", result.data.i);
938 mono_free_method (mh);
946 fprintf (stderr, "Usage is: mono-int executable args...");
951 main (int argc, char *argv [])
953 MonoAssembly *assembly;
962 assembly = mono_assembly_open (file, NULL, NULL);
964 fprintf (stderr, "Can not open image %s\n", file);
967 retval = ves_exec (assembly);
968 mono_assembly_close (assembly);
969 printf("count: %d\n", count);