added UnixWrapper, FileStream and Stream Class + various fixes
[mono.git] / mono / interpreter / interp.c
1 /*
2  * PLEASE NOTE: This is a research prototype.
3  *
4  *
5  * interp.c: Interpreter for CIL byte codes
6  *
7  * Authors:
8  *   Paolo Molaro (lupus@ximian.com)
9  *   Miguel de Icaza (miguel@ximian.com)
10  *   Dietmar Maurer (dietmar@ximian.com)
11  *
12  * (C) 2001 Ximian, Inc.
13  */
14 #define _ISOC99_SOURCE
15
16 #include <config.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <glib.h>
20 #include <ffi.h>
21 #include <math.h>
22
23
24 #ifdef HAVE_ALLOCA_H
25 #   include <alloca.h>
26 #else
27 #   ifdef __CYGWIN__
28 #      define alloca __builtin_alloca
29 #   endif
30 #endif
31
32 /* trim excessive headers */
33 #include <mono/metadata/image.h>
34 #include <mono/metadata/assembly.h>
35 #include <mono/metadata/cil-coff.h>
36 #include <mono/metadata/endian.h>
37 #include <mono/metadata/tabledefs.h>
38 #include <mono/metadata/blob.h>
39 #include <mono/metadata/tokentype.h>
40 #include <mono/cli/cli.h>
41 #include <mono/cli/types.h>
42 #include "interp.h"
43 #include "hacks.h"
44
45 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
46         a = i,
47
48 enum {
49 #include "mono/cil/opcode.def"
50         LAST = 0xff
51 };
52 #undef OPDEF
53
54 static int debug_indent_level = 0;
55 static MonoImage *corlib = NULL;
56
57 #define GET_NATI(sp) ((guint32)(sp).data.i)
58 #define CSIZE(x) (sizeof (x) / 4)
59
60 static void ves_exec_method (MonoInvocation *frame);
61
62 typedef void (*ICallMethod) (MonoMethod *mh, stackval *args);
63
64
65 static void
66 ves_real_abort (int line, MonoMethod *mh,
67                 const unsigned char *ip, stackval *stack, stackval *sp)
68 {
69         MonoMethodNormal *mm = (MonoMethodNormal *)mh;
70         fprintf (stderr, "Execution aborted in method: %s\n", mh->name);
71         fprintf (stderr, "Line=%d IP=0x%04x, Aborted execution\n", line,
72                  ip-mm->header->code);
73         g_print ("0x%04x %02x\n",
74                  ip-mm->header->code, *ip);
75         if (sp > stack)
76                 printf ("\t[%d] %d 0x%08x %0.5f\n", sp-stack, sp[-1].type, sp[-1].data.i, sp[-1].data.f);
77         exit (1);
78 }
79 #define ves_abort() ves_real_abort(__LINE__, frame->method, ip, frame->stack, sp)
80
81 /*
82  * init_class:
83  * @klass: klass that needs to be initialized
84  *
85  * This routine calls the class constructor for @class if it needs it.
86  */
87 static void
88 init_class (MonoClass *klass)
89 {
90         guint32 cols [MONO_METHOD_SIZE];
91         MonoMetadata *m;
92         MonoTableInfo *t;
93         int i;
94         MonoInvocation call;
95
96         call.parent = NULL;
97         call.retval = NULL;
98         call.obj = NULL;
99         call.stack_args = NULL;
100         
101         if (klass->inited)
102                 return;
103         if (klass->parent)
104                 init_class (klass->parent);
105         
106         m = &klass->image->metadata;
107         t = &m->tables [MONO_TABLE_METHOD];
108
109         for (i = klass->method.first; i < klass->method.last; ++i) {
110                 mono_metadata_decode_row (t, i, cols, MONO_METHOD_SIZE);
111                 
112                 if (strcmp (".cctor", mono_metadata_string_heap (m, cols [MONO_METHOD_NAME])) == 0) {
113                         call.method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (i + 1));
114                         ves_exec_method (&call);
115                         mono_free_method (call.method);
116                         klass->inited = 1;
117                         return;
118                 }
119         }
120         /* No class constructor found */
121         klass->inited = 1;
122 }
123
124 /*
125  * newobj:
126  * @image: image where the object is being referenced
127  * @token: method token to invoke
128  *
129  * This routine creates a new object based on the class where the
130  * constructor lives.x
131  */
132 static MonoObject *
133 newobj (MonoImage *image, guint32 token)
134 {
135         MonoMetadata *m = &image->metadata;
136         MonoObject *result = NULL;
137         
138         switch (mono_metadata_token_code (token)){
139         case MONO_TOKEN_METHOD_DEF: {
140                 guint32 idx = mono_metadata_typedef_from_method (m, token);
141                 result = mono_object_new (image, MONO_TOKEN_TYPE_DEF | idx);
142                 break;
143         }
144         case MONO_TOKEN_MEMBER_REF: {
145                 guint32 member_cols [MONO_MEMBERREF_SIZE];
146                 guint32 mpr_token, table, idx;
147                 
148                 mono_metadata_decode_row (
149                         &m->tables [MONO_TABLE_MEMBERREF],
150                         mono_metadata_token_index (token) - 1,
151                         member_cols, CSIZE (member_cols));
152                 mpr_token = member_cols [MONO_MEMBERREF_CLASS];
153                 table = mpr_token & 7;
154                 idx = mpr_token >> 3;
155                 
156                 if (strcmp (mono_metadata_string_heap (m, member_cols[1]), ".ctor"))
157                         g_error ("Unhandled: call to non constructor");
158
159                 switch (table){
160                 case 0: /* TypeDef */
161                         result = mono_object_new (image, MONO_TOKEN_TYPE_DEF | idx);
162                         break;
163                 case 1: /* TypeRef */
164                         result = mono_object_new (image, MONO_TOKEN_TYPE_REF | idx);
165                         break;
166                 case 2: /* ModuleRef */
167                         g_error ("Unhandled: ModuleRef");
168                         
169                 case 3: /* MethodDef */
170                         g_error ("Unhandled: MethodDef");
171                         
172                 case 4: /* TypeSpec */                  
173                         result = mono_object_new (image, MONO_TOKEN_TYPE_SPEC | idx);
174                 }
175                 break;
176         }
177         }
178         
179         if (result)
180                 init_class (result->klass);
181         return result;
182 }
183
184 static MonoMethod*
185 get_virtual_method (MonoImage *image, guint32 token, stackval *args)
186 {
187         switch (mono_metadata_token_table (token)) {
188         case MONO_TABLE_METHOD:
189         case MONO_TABLE_MEMBERREF:
190                 return mono_get_method (image, token);
191         }
192         g_error ("got virtual method: 0x%x\n", token);
193         return NULL;
194 }
195
196 /*
197  * When this is tested, export it from cli/.
198  */
199 static int
200 match_signature (const char *name, MonoMethodSignature *sig, MonoMethod *method)
201 {
202         int i;
203         MonoMethodSignature *sig2 = method->signature;
204         /* 
205          * compare the signatures.
206          * First the cheaper comparisons.
207          */
208         if (sig->param_count != sig2->param_count)
209                 return 0;
210         if (sig->hasthis != sig2->hasthis)
211                 return 0;
212         /*if (!sig->ret) {
213                 if (sig2->ret) return 0;
214         } else {
215                 if (!sig2->ret) return 0;
216                 if (sig->ret->type->type != sig2->ret->type->type)
217                         return 0;
218         }*/
219         for (i = sig->param_count - 1; i >= 0; ++i) {
220                 if (sig->params [i]->type->type != sig2->params [i]->type->type)
221                         return 0;
222         }
223         /* compare the function name */
224         return strcmp (name, method->name) == 0;
225 }
226
227 static MonoObject*
228 get_named_exception (const char *name)
229 {
230         MonoClass *klass;
231         MonoInvocation call;
232         MonoObject *o;
233         MonoMethodSignature sig = {
234                 1, /* hasthis */
235                 0,
236                 MONO_CALL_DEFAULT,
237                 0, /* param count */
238                 0, /* sentinel pos */
239                 NULL, /* retval -> void */
240                 NULL, /* params */
241                 0
242         };
243         int i;
244         guint32 tdef = mono_typedef_from_name (corlib, name, "System", NULL);
245         o = newobj (corlib, tdef);
246         klass = mono_class_get (corlib, tdef);
247         call.method = NULL;
248         for (i = 0; i < klass->method.count; ++i) {
249                 if (match_signature (".ctor", &sig, klass->methods [i])) {
250                         call.method = klass->methods [i];
251                         break;
252                 }
253         }
254         g_assert (call.method);
255         call.obj = o;
256         ves_exec_method (&call);
257         return o;
258 }
259
260 static MonoObject*
261 get_exception_divide_by_zero ()
262 {
263         static MonoObject *ex = NULL;
264         if (ex)
265                 return ex;
266         ex = get_named_exception ("DivideByZeroException");
267         return ex;
268 }
269
270 static int
271 mono_isinst (MonoObject *obj, MonoClass *klass)
272 {
273         MonoClass *oklass = obj->klass;
274         while (oklass) {
275                 if (oklass == klass)
276                         return 1;
277                 oklass = oklass->parent;
278         }
279         return 0;
280 }
281
282 static stackval
283 stackval_from_data (MonoType *type, const char *data)
284 {
285         stackval result;
286         if (type->byref) {
287                 result.type = VAL_OBJ;
288                 result.data.p = *(gpointer*)data;
289                 return result;
290         }
291         switch (type->type) {
292         case MONO_TYPE_I1:
293                 result.type = VAL_I32;
294                 result.data.i = *(gint8*)data;
295                 break;
296         case MONO_TYPE_U1:
297         case MONO_TYPE_BOOLEAN:
298                 result.type = VAL_I32;
299                 result.data.i = *(guint8*)data;
300                 break;
301         case MONO_TYPE_I2:
302                 result.type = VAL_I32;
303                 result.data.i = *(gint16*)data;
304                 break;
305         case MONO_TYPE_U2:
306         case MONO_TYPE_CHAR:
307                 result.type = VAL_I32;
308                 result.data.i = *(guint16*)data;
309                 break;
310         case MONO_TYPE_I4:
311                 result.type = VAL_I32;
312                 result.data.i = *(gint32*)data;
313                 break;
314         case MONO_TYPE_U4:
315                 result.type = VAL_I32;
316                 result.data.i = *(guint32*)data;
317                 break;
318         case MONO_TYPE_R4:
319                 result.type = VAL_DOUBLE;
320                 result.data.f = *(float*)data;
321                 break;
322         case MONO_TYPE_R8:
323                 result.type = VAL_DOUBLE;
324                 result.data.f = *(double*)data;
325                 break;
326         case MONO_TYPE_STRING:
327         case MONO_TYPE_SZARRAY:
328         case MONO_TYPE_CLASS:
329         case MONO_TYPE_OBJECT:
330         case MONO_TYPE_ARRAY:
331         case MONO_TYPE_PTR:
332                 result.type = VAL_OBJ;
333                 result.data.p = *(gpointer*)data;
334                 break;
335         default:
336                 g_warning ("got type %x", type->type);
337                 g_assert_not_reached ();
338         }
339         return result;
340 }
341
342 static void
343 stackval_to_data (MonoType *type, stackval *val, char *data)
344 {
345         if (type->byref) {
346                 *(gpointer*)data = val->data.p;
347                 return;
348         }
349         switch (type->type) {
350         case MONO_TYPE_I1:
351         case MONO_TYPE_U1:
352                 *(guint8*)data = val->data.i;
353                 break;
354         case MONO_TYPE_BOOLEAN:
355                 *(guint8*)data = (val->data.i != 0);
356                 break;
357         case MONO_TYPE_I2:
358         case MONO_TYPE_U2:
359                 *(guint16*)data = val->data.i;
360                 break;
361         case MONO_TYPE_I4:
362         case MONO_TYPE_U4:
363                 *(gint32*)data = val->data.i;
364                 break;
365         case MONO_TYPE_R4:
366                 *(float*)data = val->data.f;
367                 break;
368         case MONO_TYPE_R8:
369                 *(double*)data = val->data.f;
370                 break;
371         case MONO_TYPE_STRING:
372         case MONO_TYPE_SZARRAY:
373         case MONO_TYPE_CLASS:
374         case MONO_TYPE_OBJECT:
375         case MONO_TYPE_ARRAY:
376         case MONO_TYPE_PTR:
377                 *(gpointer*)data = val->data.p;
378                 break;
379         default:
380                 g_warning ("got type %x", type->type);
381                 g_assert_not_reached ();
382         }
383 }
384
385 static char *
386 mono_get_ansi_string (MonoObject *o)
387 {
388         MonoStringObject *s = (MonoStringObject *)o;
389         char *as, *vector;
390         int i;
391
392         g_assert (o != NULL);
393
394         if (!s->length)
395                 return g_strdup ("");
396
397         vector = s->c_str->vector;
398
399         g_assert (vector != NULL);
400
401         as = g_malloc (s->length + 1);
402
403         /* fixme: replace with a real unicode/ansi conversion */
404         for (i = 0; i < s->length; i++) {
405                 as [i] = vector [i*2];
406         }
407
408         as [i] = '\0';
409
410         return as;
411 }
412
413 static void 
414 ves_pinvoke_method (MonoMethod *mh, stackval *sp)
415 {
416         MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)mh;
417         gpointer *values;
418         float *tmp_float;
419         char **tmp_string;
420         int i, acount, rsize, align;
421         gpointer res = NULL; 
422         GSList *t, *l = NULL;
423
424         acount = mh->signature->param_count;
425
426         values = alloca (sizeof (gpointer) * acount);
427
428         /* fixme: only works on little endian mashines */
429
430         for (i = 0; i < acount; i++) {
431
432                 switch (mh->signature->params [i]->type->type) {
433
434                 case MONO_TYPE_I1:
435                 case MONO_TYPE_U1:
436                 case MONO_TYPE_BOOLEAN:
437                 case MONO_TYPE_I2:
438                 case MONO_TYPE_U2:
439                 case MONO_TYPE_CHAR:
440                 case MONO_TYPE_I4:
441                 case MONO_TYPE_U4:
442                         values[i] = &sp [i].data.i;
443                         break;
444                 case MONO_TYPE_R4:
445                         tmp_float = alloca (sizeof (float));
446                         *tmp_float = sp [i].data.f;
447                         values[i] = tmp_float;
448                         break;
449                 case MONO_TYPE_R8:
450                         values[i] = &sp [i].data.f;
451                         break;
452                 case MONO_TYPE_STRING:
453                         g_assert (sp [i].type == VAL_OBJ);
454
455                         if (mh->flags & PINVOKE_ATTRIBUTE_CHAR_SET_ANSI && sp [i].data.p) {
456                                 tmp_string = alloca (sizeof (char *));
457                                 *tmp_string = mono_get_ansi_string (sp [i].data.p);
458                                 l = g_slist_prepend (l, *tmp_string);
459                                 values[i] = tmp_string;                         
460                         } else {
461                                 /* 
462                                  * fixme: may we pass the object - I assume 
463                                  * that is wrong ?? 
464                                  */
465                                 values[i] = &sp [i].data.p;
466                         }
467                         
468                         break;
469                 default:
470                         g_warning ("not implemented %x", 
471                                    mh->signature->params [i]->type->type);
472                         g_assert_not_reached ();
473                 }
474
475         }
476
477         if ((rsize = mono_type_size (mh->signature->ret->type, &align)))
478                 res = alloca (rsize);
479
480         ffi_call (piinfo->cif, mh->addr, res, values);
481                 
482         t = l;
483         while (t) {
484                 g_free (t->data);
485                 t = t->next;
486         }
487
488         g_slist_free (l);
489
490         if (mh->signature->ret->type)
491                 *sp = stackval_from_data (mh->signature->ret->type, res);
492                         
493 }
494
495 #define DEBUG_INTERP 0
496 #if DEBUG_INTERP
497 #define OPDEF(a,b,c,d,e,f,g,h,i,j)  b,
498 static char *opcode_names[] = {
499 #include "mono/cil/opcode.def"
500         NULL
501 };
502 #undef OPDEF
503
504 static void
505 output_indent (void)
506 {
507         int h;
508
509         for (h = 0; h < debug_indent_level; h++)
510                 g_print ("  ");
511 }
512
513 static void
514 dump_stack (stackval *stack, stackval *sp)
515 {
516         stackval *s = stack;
517         
518         if (sp == stack)
519                 return;
520         
521         output_indent ();
522         g_print ("stack: ");
523                 
524         while (s < sp) {
525                 switch (s->type) {
526                 case VAL_I32: g_print ("[%d] ", s->data.i); break;
527                 case VAL_I64: g_print ("[%lld] ", s->data.l); break;
528                 case VAL_DOUBLE: g_print ("[%0.5f] ", s->data.f); break;
529                 default: g_print ("[%p] ", s->data.p); break;
530                 }
531                 ++s;
532         }
533 }
534
535 #endif
536
537 static MonoType 
538 method_this = {
539         MONO_TYPE_CLASS, 
540         0, 
541         1, /* byref */
542         0,
543         {0}
544 };
545
546 #define LOCAL_POS(n)            (locals_pointers [(n)])
547 #define LOCAL_TYPE(header, n)   ((header)->locals [(n)])
548
549 #define ARG_POS(n)              (args_pointers [(n)])
550 #define ARG_TYPE(sig, n)        ((n) ? (sig)->params [(n) - (sig)->hasthis]->type : \
551                                 (sig)->hasthis ? &method_this: (sig)->params [(0)]->type)
552
553 #define THROW_EX(exception,ex_ip)       \
554                 do {\
555                         frame->ip = (ex_ip);            \
556                         frame->ex = (exception);        \
557                         goto handle_exception;  \
558                 } while (0)
559
560 /*
561  * Need to optimize ALU ops when natural int == int32 
562  *
563  * IDEA: if we maintain a stack of ip, sp to be checked
564  * in the return opcode, we could inline simple methods that don't
565  * use the stack or local variables....
566  * 
567  * The {,.S} versions of many opcodes can/should be merged to reduce code
568  * duplication.
569  * 
570  */
571 static void 
572 ves_exec_method (MonoInvocation *frame)
573 {
574         MonoInvocation child_frame;
575         MonoMethodHeader *header;
576         MonoMethodSignature *signature;
577         MonoImage *image;
578         const unsigned char *endfinally_ip;
579         register const unsigned char *ip;
580         register stackval *sp;
581         void **locals_pointers;
582         void **args_pointers;
583         GOTO_LABEL_VARS;
584
585         if (frame->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
586                 ICallMethod icall = frame->method->addr;
587
588                 icall (frame->method, frame->stack_args);
589                 return;
590         }
591
592         if (frame->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
593                 ves_pinvoke_method (frame->method, frame->stack_args);
594                 return;
595         } 
596
597         header = ((MonoMethodNormal *)frame->method)->header;
598         signature = frame->method->signature;
599         image = frame->method->image;
600
601 #if DEBUG_INTERP
602         debug_indent_level++;
603         output_indent ();
604         g_print ("Entering %s\n", frame->method->name);
605 #endif
606
607         /*
608          * with alloca we get the expected huge performance gain
609          * stackval *stack = g_new0(stackval, header->max_stack);
610          */
611
612         sp = frame->stack = alloca (sizeof (stackval) * header->max_stack);
613
614         if (header->num_locals) {
615                 int i, align, size, offset = 0;
616
617                 frame->locals = alloca (header->locals_size);
618                 locals_pointers = alloca (sizeof(void*) * header->num_locals);
619                 /* 
620                  * yes, we do it unconditionally, because it needs to be done for
621                  * some cases anyway and checking for that would be even slower.
622                  */
623                 memset (frame->locals, 0, header->locals_size);
624                 for (i = 0; i < header->num_locals; ++i) {
625                         locals_pointers [i] = frame->locals + offset;
626                         size = mono_type_size (header->locals [i], &align);
627                         offset += offset % align;
628                         offset += size;
629                 }
630         }
631         /*
632          * Copy args from stack_args to args.
633          */
634         if (signature->params_size) {
635                 int i, align, size, offset = 0;
636                 int has_this = signature->hasthis;
637
638                 frame->args = alloca (signature->params_size);
639                 args_pointers = alloca (sizeof(void*) * (signature->param_count + has_this));
640                 if (has_this) {
641                         args_pointers [0] = frame->args;
642                         *(gpointer*) frame->args = frame->obj;
643                         offset += sizeof (gpointer);
644                 }
645                 for (i = 0; i < signature->param_count; ++i) {
646                         args_pointers [i + has_this] = frame->args + offset;
647                         stackval_to_data (signature->params [i]->type, frame->stack_args + i, frame->args + offset);
648                         size = mono_type_size (signature->params [i]->type, &align);
649                         offset += offset % align;
650                         offset += size;
651                 }
652         }
653
654         child_frame.parent = frame;
655         frame->child = &child_frame;
656         frame->ex = NULL;
657
658         /* ready to go */
659         ip = header->code;
660
661         /*
662          * using while (ip < end) may result in a 15% performance drop, 
663          * but it may be useful for debug
664          */
665         while (1) {
666         main_loop:
667                 /*g_assert (sp >= stack);*/
668 #if DEBUG_INTERP
669                 dump_stack (frame->stack, sp);
670                 g_print ("\n");
671                 output_indent ();
672                 g_print ("0x%04x: %s\n", ip-header->code,
673                          *ip == 0xfe ? opcode_names [256 + ip [1]] : opcode_names [*ip]);
674 #endif
675                 
676                 SWITCH (*ip) {
677                 CASE (CEE_NOP) 
678                         ++ip;
679                         BREAK;
680                 CASE (CEE_BREAK)
681                         ++ip;
682                         G_BREAKPOINT (); /* this is not portable... */
683                         BREAK;
684                 CASE (CEE_LDARG_0)
685                 CASE (CEE_LDARG_1)
686                 CASE (CEE_LDARG_2)
687                 CASE (CEE_LDARG_3) {
688                         int n = (*ip)-CEE_LDARG_0;
689                         ++ip;
690                         *sp = stackval_from_data (ARG_TYPE (signature, n), ARG_POS (n));
691                         ++sp;
692                         BREAK;
693                 }
694                 CASE (CEE_LDLOC_0)
695                 CASE (CEE_LDLOC_1)
696                 CASE (CEE_LDLOC_2)
697                 CASE (CEE_LDLOC_3) {
698                         int n = (*ip)-CEE_LDLOC_0;
699                         ++ip;
700                         *sp = stackval_from_data (LOCAL_TYPE (header, n), LOCAL_POS (n));
701                         ++sp;
702                         BREAK;
703                 }
704                 CASE (CEE_STLOC_0)
705                 CASE (CEE_STLOC_1)
706                 CASE (CEE_STLOC_2)
707                 CASE (CEE_STLOC_3) {
708                         int n = (*ip)-CEE_STLOC_0;
709                         ++ip;
710                         --sp;
711                         stackval_to_data (LOCAL_TYPE (header, n), sp, LOCAL_POS (n));
712                         BREAK;
713                 }
714                 CASE (CEE_LDARG_S)
715                         ++ip;
716                         *sp = stackval_from_data (ARG_TYPE (signature, *ip), ARG_POS (*ip));
717                         ++sp;
718                         ++ip;
719                         BREAK;
720                 CASE (CEE_LDARGA_S)
721                         ++ip;
722                         sp->type = VAL_TP;
723                         sp->data.p = ARG_POS (*ip);
724                         ++sp;
725                         ++ip;
726                         BREAK;
727                 CASE (CEE_STARG_S) ves_abort(); BREAK;
728                 CASE (CEE_LDLOC_S)
729                         ++ip;
730                         *sp = stackval_from_data (LOCAL_TYPE (header, *ip), LOCAL_POS (*ip));
731                         ++ip;
732                         ++sp;
733                         BREAK;
734                 CASE (CEE_LDLOCA_S)
735                         ++ip;
736                         sp->type = VAL_TP;
737                         sp->data.p = LOCAL_POS (*ip);
738                         ++sp;
739                         ++ip;
740                         BREAK;
741                 CASE (CEE_STLOC_S)
742                         ++ip;
743                         --sp;
744                         stackval_to_data (LOCAL_TYPE (header, *ip), sp, LOCAL_POS (*ip));
745                         ++ip;
746                         BREAK;
747                 CASE (CEE_LDNULL) 
748                         ++ip;
749                         sp->type = VAL_OBJ;
750                         sp->data.p = NULL;
751                         ++sp;
752                         BREAK;
753                 CASE (CEE_LDC_I4_M1)
754                         ++ip;
755                         sp->type = VAL_I32;
756                         sp->data.i = -1;
757                         ++sp;
758                         BREAK;
759                 CASE (CEE_LDC_I4_0)
760                 CASE (CEE_LDC_I4_1)
761                 CASE (CEE_LDC_I4_2)
762                 CASE (CEE_LDC_I4_3)
763                 CASE (CEE_LDC_I4_4)
764                 CASE (CEE_LDC_I4_5)
765                 CASE (CEE_LDC_I4_6)
766                 CASE (CEE_LDC_I4_7)
767                 CASE (CEE_LDC_I4_8)
768                         sp->type = VAL_I32;
769                         sp->data.i = (*ip) - CEE_LDC_I4_0;
770                         ++sp;
771                         ++ip;
772                         BREAK;
773                 CASE (CEE_LDC_I4_S) 
774                         ++ip;
775                         sp->type = VAL_I32;
776                         sp->data.i = *ip; /* FIXME: signed? */
777                         ++ip;
778                         ++sp;
779                         BREAK;
780                 CASE (CEE_LDC_I4)
781                         ++ip;
782                         sp->type = VAL_I32;
783                         sp->data.i = read32 (ip);
784                         ip += 4;
785                         ++sp;
786                         BREAK;
787                 CASE (CEE_LDC_I8)
788                         ++ip;
789                         sp->type = VAL_I64;
790                         sp->data.i = read64 (ip);
791                         ip += 8;
792                         ++sp;
793                         BREAK;
794                 CASE (CEE_LDC_R4)
795                         ++ip;
796                         sp->type = VAL_DOUBLE;
797                         /* FIXME: ENOENDIAN */
798                         sp->data.f = *(float*)(ip);
799                         ip += sizeof (float);
800                         ++sp;
801                         BREAK;
802                 CASE (CEE_LDC_R8) 
803                         ++ip;
804                         sp->type = VAL_DOUBLE;
805                         /* FIXME: ENOENDIAN */
806                         sp->data.f = *(double*) (ip);
807                         ip += sizeof (double);
808                         ++sp;
809                         BREAK;
810                 CASE (CEE_UNUSED99) ves_abort (); BREAK;
811                 CASE (CEE_DUP) 
812                         *sp = sp [-1]; 
813                         ++sp; 
814                         ++ip; 
815                         BREAK;
816                 CASE (CEE_POP)
817                         ++ip;
818                         --sp;
819                         BREAK;
820                 CASE (CEE_JMP) ves_abort(); BREAK;
821                 CASE (CEE_CALLVIRT) /* Fall through */
822                 CASE (CEE_CALL) {
823                         MonoMethodSignature *csignature;
824                         stackval retval;
825                         guint32 token;
826                         int virtual = *ip == CEE_CALLVIRT;
827
828                         frame->ip = ip;
829                         
830                         ++ip;
831                         token = read32 (ip);
832                         ip += 4;
833                         if (virtual)
834                                 child_frame.method = get_virtual_method (image, token, sp);
835                         else
836                                 child_frame.method = mono_get_method (image, token);
837                         csignature = child_frame.method->signature;
838                         g_assert (csignature->call_convention == MONO_CALL_DEFAULT);
839
840                         /* decrement by the actual number of args */
841                         if (csignature->param_count) {
842                                 sp -= csignature->param_count;
843                                 child_frame.stack_args = sp;
844                         } else {
845                                 child_frame.stack_args = NULL;
846                         }
847                         if (csignature->hasthis) {
848                                 g_assert (sp >= frame->stack);
849                                 --sp;
850                                 g_assert (sp->type == VAL_OBJ);
851                                 child_frame.obj = sp->data.p;
852                         } else {
853                                 child_frame.obj = NULL;
854                         }
855                         if (csignature->ret->type) {
856                                 /* FIXME: handle valuetype */
857                                 child_frame.retval = &retval;
858                         } else {
859                                 child_frame.retval = NULL;
860                         }
861                         ves_exec_method (&child_frame);
862                         if (child_frame.ex) {
863                                 /*
864                                  * An exception occurred, need to run finally, fault and catch handlers..
865                                  */
866                                 frame->ex = child_frame.ex;
867                                 goto handle_finally;
868                         }
869
870                         /* need to handle typedbyref ... */
871                         if (csignature->ret->type) {
872                                 *sp = retval;
873                                 sp++;
874                         }
875                         BREAK;
876                 }
877                 CASE (CEE_CALLI) ves_abort(); BREAK;
878                 CASE (CEE_RET)
879                         if (signature->ret->type) {
880                                 --sp;
881                                 *frame->retval = *sp;
882                         }
883                         if (sp > frame->stack)
884                                 g_warning ("more values on stack: %d", sp-frame->stack);
885
886 #if DEBUG_INTERP
887                         debug_indent_level--;
888 #endif
889                         return;
890                 CASE (CEE_BR_S)
891                         ++ip;
892                         ip += (signed char) *ip;
893                         ++ip;
894                         BREAK;
895                 CASE (CEE_BRFALSE_S) {
896                         int result;
897                         ++ip;
898                         --sp;
899                         switch (sp->type) {
900                         case VAL_I32: result = sp->data.i == 0; break;
901                         case VAL_I64: result = sp->data.l == 0; break;
902                         case VAL_DOUBLE: result = sp->data.f ? 0: 1; break;
903                         default: result = sp->data.p == NULL; break;
904                         }
905                         if (result)
906                                 ip += (signed char)*ip;
907                         ++ip;
908                         BREAK;
909                 }
910                 CASE (CEE_BRTRUE_S) {
911                         int result;
912                         ++ip;
913                         --sp;
914                         switch (sp->type) {
915                         case VAL_I32: result = sp->data.i != 0; break;
916                         case VAL_I64: result = sp->data.l != 0; break;
917                         case VAL_DOUBLE: result = sp->data.f ? 1 : 0; break;
918                         default: result = sp->data.p != NULL; break;
919                         }
920                         if (result)
921                                 ip += (signed char)*ip;
922                         ++ip;
923                         BREAK;
924                 }
925                 CASE (CEE_BEQ_S) {
926                         int result;
927                         ++ip;
928                         sp -= 2;
929                         if (sp->type == VAL_I32)
930                                 result = sp [0].data.i == GET_NATI (sp [1]);
931                         else if (sp->type == VAL_I64)
932                                 result = sp [0].data.l == sp [1].data.l;
933                         else if (sp->type == VAL_DOUBLE)
934                                 result = sp [0].data.f == sp [1].data.f;
935                         else
936                                 result = GET_NATI (sp [0]) == GET_NATI (sp [1]);
937                         if (result)
938                                 ip += (signed char)*ip;
939                         ++ip;
940                         BREAK;
941                 }
942                 CASE (CEE_BGE_S) {
943                         int result;
944                         ++ip;
945                         sp -= 2;
946                         if (sp->type == VAL_I32)
947                                 result = sp [0].data.i >= GET_NATI (sp [1]);
948                         else if (sp->type == VAL_I64)
949                                 result = sp [0].data.l >= sp [1].data.l;
950                         else if (sp->type == VAL_DOUBLE)
951                                 result = sp [0].data.f >= sp [1].data.f;
952                         else
953                                 result = GET_NATI (sp [0]) >= GET_NATI (sp [1]);
954                         if (result)
955                                 ip += (signed char)*ip;
956                         ++ip;
957                         BREAK;
958                 }
959                 CASE (CEE_BGT_S) {
960                         int result;
961                         ++ip;
962                         sp -= 2;
963                         if (sp->type == VAL_I32)
964                                 result = sp [0].data.i > GET_NATI (sp [1]);
965                         else if (sp->type == VAL_I64)
966                                 result = sp [0].data.l > sp [1].data.l;
967                         else if (sp->type == VAL_DOUBLE)
968                                 result = sp [0].data.f > sp [1].data.f;
969                         else
970                                 result = GET_NATI (sp [0]) > GET_NATI (sp [1]);
971                         if (result)
972                                 ip += (signed char)*ip;
973                         ++ip;
974                         BREAK;
975                 }
976                 CASE (CEE_BLT_S) {
977                         int result;
978                         ++ip;
979                         sp -= 2;
980                         if (sp->type == VAL_I32)
981                                 result = sp[0].data.i < GET_NATI(sp[1]);
982                         else if (sp->type == VAL_I64)
983                                 result = sp[0].data.l < sp[1].data.l;
984                         else if (sp->type == VAL_DOUBLE)
985                                 result = sp[0].data.f < sp[1].data.f;
986                         else
987                                 result = GET_NATI(sp[0]) < GET_NATI(sp[1]);
988                         if (result)
989                                 ip += (signed char)*ip;
990                         ++ip;
991                         BREAK;
992                 }
993                 CASE (CEE_BLE_S) {
994                         int result;
995                         ++ip;
996                         sp -= 2;
997
998                         if (sp->type == VAL_I32)
999                                 result = sp [0].data.i <= GET_NATI (sp [1]);
1000                         else if (sp->type == VAL_I64)
1001                                 result = sp [0].data.l <= sp [1].data.l;
1002                         else if (sp->type == VAL_DOUBLE)
1003                                 result = sp [0].data.f <= sp [1].data.f;
1004                         else {
1005                                 /*
1006                                  * FIXME: here and in other places GET_NATI on the left side 
1007                                  * _will_ be wrong when we change the macro to work on 64 buts 
1008                                  * systems.
1009                                  */
1010                                 result = GET_NATI (sp [0]) <= GET_NATI (sp [1]);
1011                         }
1012                         if (result)
1013                                 ip += (signed char)*ip;
1014                         ++ip;
1015                         BREAK;
1016                 }
1017                 CASE (CEE_BNE_UN_S) {
1018                         int result;
1019                         ++ip;
1020                         sp -= 2;
1021                         if (sp->type == VAL_I32)
1022                                 result = (guint32)sp [0].data.i != (guint32)GET_NATI (sp [1]);
1023                         else if (sp->type == VAL_I64)
1024                                 result = (guint64)sp [0].data.l != (guint64)sp [1].data.l;
1025                         else if (sp->type == VAL_DOUBLE)
1026                                 result = isunordered (sp [0].data.f, sp [1].data.f) ||
1027                                         (sp [0].data.f != sp [1].data.f);
1028                         else
1029                                 result = GET_NATI (sp [0]) != GET_NATI (sp [1]);
1030                         if (result)
1031                                 ip += (signed char)*ip;
1032                         ++ip;
1033                         BREAK;
1034                 }
1035                 CASE (CEE_BGE_UN_S) {
1036                         int result;
1037                         ++ip;
1038                         sp -= 2;
1039                         if (sp->type == VAL_I32)
1040                                 result = (guint32)sp [0].data.i >= (guint32)GET_NATI (sp [1]);
1041                         else if (sp->type == VAL_I64)
1042                                 result = (guint64)sp [0].data.l >= (guint64)sp [1].data.l;
1043                         else if (sp->type == VAL_DOUBLE)
1044                                 result = !isless (sp [0].data.f,sp [1].data.f);
1045                         else
1046                                 result = GET_NATI (sp [0]) >= GET_NATI (sp [1]);
1047                         if (result)
1048                                 ip += (signed char)*ip;
1049                         ++ip;
1050                         BREAK;
1051                 }
1052                 CASE (CEE_BGT_UN_S) {
1053                         int result;
1054                         ++ip;
1055                         sp -= 2;
1056                         if (sp->type == VAL_I32)
1057                                 result = (guint32)sp [0].data.i > (guint32)GET_NATI (sp [1]);
1058                         else if (sp->type == VAL_I64)
1059                                 result = (guint64)sp [0].data.l > (guint64)sp [1].data.l;
1060                         else if (sp->type == VAL_DOUBLE)
1061                                 result = isgreater (sp [0].data.f, sp [1].data.f);
1062                         else
1063                                 result = GET_NATI (sp [0]) > GET_NATI (sp [1]);
1064                         if (result)
1065                                 ip += (signed char)*ip;
1066                         ++ip;
1067                         BREAK;
1068                 }
1069                 CASE (CEE_BLE_UN_S) {
1070                         int result;
1071                         ++ip;
1072                         sp -= 2;
1073                         if (sp->type == VAL_I32)
1074                                 result = (guint32)sp [0].data.i <= (guint32)GET_NATI (sp [1]);
1075                         else if (sp->type == VAL_I64)
1076                                 result = (guint64)sp [0].data.l <= (guint64)sp [1].data.l;
1077                         else if (sp->type == VAL_DOUBLE)
1078                                 result = islessequal (sp [0].data.f, sp [1].data.f);
1079                         else
1080                                 result = GET_NATI (sp [0]) <= GET_NATI (sp [1]);
1081                         if (result)
1082                                 ip += (signed char)*ip;
1083                         ++ip;
1084                         BREAK;
1085                 }
1086                 CASE (CEE_BLT_UN_S) {
1087                         int result;
1088                         ++ip;
1089                         sp -= 2;
1090                         if (sp->type == VAL_I32)
1091                                 result = (guint32)sp[0].data.i < (guint32)GET_NATI(sp[1]);
1092                         else if (sp->type == VAL_I64)
1093                                 result = (guint64)sp[0].data.l < (guint64)sp[1].data.l;
1094                         else if (sp->type == VAL_DOUBLE)
1095                                 result = isunordered (sp [0].data.f, sp [1].data.f) ||
1096                                         (sp [0].data.f < sp [1].data.f);
1097                         else
1098                                 result = GET_NATI(sp[0]) < GET_NATI(sp[1]);
1099                         if (result)
1100                                 ip += (signed char)*ip;
1101                         ++ip;
1102                         BREAK;
1103                 }
1104                 CASE (CEE_BR) ves_abort(); BREAK;
1105                 CASE (CEE_BRFALSE) ves_abort(); BREAK;
1106                 CASE (CEE_BRTRUE) ves_abort(); BREAK;
1107                 CASE (CEE_BEQ) ves_abort(); BREAK;
1108                 CASE (CEE_BGE) ves_abort(); BREAK;
1109                 CASE (CEE_BGT) ves_abort(); BREAK;
1110                 CASE (CEE_BLE) ves_abort(); BREAK;
1111                 CASE (CEE_BLT) ves_abort(); BREAK;
1112                 CASE (CEE_BNE_UN) ves_abort(); BREAK;
1113                 CASE (CEE_BGE_UN) ves_abort(); BREAK;
1114                 CASE (CEE_BGT_UN) ves_abort(); BREAK;
1115                 CASE (CEE_BLE_UN) ves_abort(); BREAK;
1116                 CASE (CEE_BLT_UN) ves_abort(); BREAK;
1117                 CASE (CEE_SWITCH) {
1118                         guint32 n;
1119                         const unsigned char *st;
1120                         ++ip;
1121                         n = read32 (ip);
1122                         ip += 4;
1123                         st = ip + sizeof (gint32) * n;
1124                         --sp;
1125                         if ((guint32)sp->data.i < n) {
1126                                 gint offset;
1127                                 ip += sizeof (gint32) * (guint32)sp->data.i;
1128                                 offset = read32 (ip);
1129                                 ip = st + offset;
1130                         } else {
1131                                 ip = st;
1132                         }
1133                         BREAK;
1134                 }
1135                 CASE (CEE_LDIND_I1)
1136                         ++ip;
1137                         sp[-1].type = VAL_I32;
1138                         sp[-1].data.i = *(gint8*)sp[-1].data.p;
1139                         BREAK;
1140                 CASE (CEE_LDIND_U1)
1141                         ++ip;
1142                         sp[-1].type = VAL_I32;
1143                         sp[-1].data.i = *(guint8*)sp[-1].data.p;
1144                         BREAK;
1145                 CASE (CEE_LDIND_I2)
1146                         ++ip;
1147                         sp[-1].type = VAL_I32;
1148                         sp[-1].data.i = *(gint16*)sp[-1].data.p;
1149                         BREAK;
1150                 CASE (CEE_LDIND_U2)
1151                         ++ip;
1152                         sp[-1].type = VAL_I32;
1153                         sp[-1].data.i = *(guint16*)sp[-1].data.p;
1154                         BREAK;
1155                 CASE (CEE_LDIND_I4) /* Fall through */
1156                 CASE (CEE_LDIND_U4)
1157                         ++ip;
1158                         sp[-1].type = VAL_I32;
1159                         sp[-1].data.i = *(gint32*)sp[-1].data.p;
1160                         BREAK;
1161                 CASE (CEE_LDIND_I8)
1162                         ++ip;
1163                         sp[-1].type = VAL_I64;
1164                         sp[-1].data.l = *(gint64*)sp[-1].data.p;
1165                         BREAK;
1166                 CASE (CEE_LDIND_I)
1167                         ++ip;
1168                         sp[-1].type = VAL_NATI;
1169                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
1170                         BREAK;
1171                 CASE (CEE_LDIND_R4)
1172                         ++ip;
1173                         sp[-1].type = VAL_DOUBLE;
1174                         sp[-1].data.i = *(gfloat*)sp[-1].data.p;
1175                         BREAK;
1176                 CASE (CEE_LDIND_R8)
1177                         ++ip;
1178                         sp[-1].type = VAL_DOUBLE;
1179                         sp[-1].data.i = *(gdouble*)sp[-1].data.p;
1180                         BREAK;
1181                 CASE (CEE_LDIND_REF)
1182                         ++ip;
1183                         sp[-1].type = VAL_OBJ;
1184                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
1185                         BREAK;
1186                 CASE (CEE_STIND_REF)
1187                         ++ip;
1188                         sp -= 2;
1189                         *(gpointer*)sp->data.p = sp[1].data.p;
1190                         BREAK;
1191                 CASE (CEE_STIND_I1)
1192                         ++ip;
1193                         sp -= 2;
1194                         *(gint8*)sp->data.p = (gint8)sp[1].data.i;
1195                         BREAK;
1196                 CASE (CEE_STIND_I2)
1197                         ++ip;
1198                         sp -= 2;
1199                         *(gint16*)sp->data.p = (gint16)sp[1].data.i;
1200                         BREAK;
1201                 CASE (CEE_STIND_I4)
1202                         ++ip;
1203                         sp -= 2;
1204                         *(gint32*)sp->data.p = sp[1].data.i;
1205                         BREAK;
1206                 CASE (CEE_STIND_I8)
1207                         ++ip;
1208                         sp -= 2;
1209                         *(gint64*)sp->data.p = sp[1].data.l;
1210                         BREAK;
1211                 CASE (CEE_STIND_R4)
1212                         ++ip;
1213                         sp -= 2;
1214                         *(gfloat*)sp->data.p = (gfloat)sp[1].data.f;
1215                         BREAK;
1216                 CASE (CEE_STIND_R8)
1217                         ++ip;
1218                         sp -= 2;
1219                         *(gdouble*)sp->data.p = sp[1].data.f;
1220                         BREAK;
1221                 CASE (CEE_ADD)
1222                         ++ip;
1223                         --sp;
1224                         /* should probably consider the pointers as unsigned */
1225                         if (sp->type == VAL_I32)
1226                                 sp [-1].data.i += GET_NATI (sp [0]);
1227                         else if (sp->type == VAL_I64)
1228                                 sp [-1].data.l += sp [0].data.l;
1229                         else if (sp->type == VAL_DOUBLE)
1230                                 sp [-1].data.f += sp [0].data.f;
1231                         else
1232                                 (char*)sp [-1].data.p += GET_NATI (sp [0]);
1233                         BREAK;
1234                 CASE (CEE_SUB)
1235                         ++ip;
1236                         --sp;
1237                         /* should probably consider the pointers as unsigned */
1238                         if (sp->type == VAL_I32)
1239                                 sp [-1].data.i -= GET_NATI (sp [0]);
1240                         else if (sp->type == VAL_I64)
1241                                 sp [-1].data.l -= sp [0].data.l;
1242                         else if (sp->type == VAL_DOUBLE)
1243                                 sp [-1].data.f -= sp [0].data.f;
1244                         else
1245                                 (char*)sp [-1].data.p -= GET_NATI (sp [0]);
1246                         BREAK;
1247                 CASE (CEE_MUL)
1248                         ++ip;
1249                         --sp;
1250                         if (sp->type == VAL_I32)
1251                                 sp [-1].data.i *= GET_NATI (sp [0]);
1252                         else if (sp->type == VAL_I64)
1253                                 sp [-1].data.l *= sp [0].data.l;
1254                         else if (sp->type == VAL_DOUBLE)
1255                                 sp [-1].data.f *= sp [0].data.f;
1256                         BREAK;
1257                 CASE (CEE_DIV)
1258                         ++ip;
1259                         --sp;
1260                         if (sp->type == VAL_I32) {
1261                                 /* 
1262                                  * FIXME: move to handle also the other types
1263                                  */
1264                                 if (GET_NATI (sp [0]) == 0)
1265                                         THROW_EX (get_exception_divide_by_zero (), ip - 1);
1266                                 sp [-1].data.i /= GET_NATI (sp [0]);
1267                         } else if (sp->type == VAL_I64)
1268                                 sp [-1].data.l /= sp [0].data.l;
1269                         else if (sp->type == VAL_DOUBLE)
1270                                 sp [-1].data.f /= sp [0].data.f;
1271                         BREAK;
1272                 CASE (CEE_DIV_UN)
1273                         ++ip;
1274                         --sp;
1275                         if (sp->type == VAL_I32)
1276                                 (guint32)sp [-1].data.i /= (guint32)GET_NATI (sp [0]);
1277                         else if (sp->type == VAL_I64)
1278                                 (guint64)sp [-1].data.l /= (guint64)sp [0].data.l;
1279                         else if (sp->type == VAL_NATI)
1280                                 (gulong)sp [-1].data.p /= (gulong)sp [0].data.p;
1281                         BREAK;
1282                 CASE (CEE_REM)
1283                         ++ip;
1284                         --sp;
1285                         if (sp->type == VAL_I32)
1286                                 sp [-1].data.i %= GET_NATI (sp [0]);
1287                         else if (sp->type == VAL_I64)
1288                                 sp [-1].data.l %= sp [0].data.l;
1289                         else if (sp->type == VAL_DOUBLE)
1290                                 /* FIXME: what do we actually fo here? */
1291                                 sp [-1].data.f = 0;
1292                         else
1293                                 GET_NATI (sp [-1]) %= GET_NATI (sp [0]);
1294                         BREAK;
1295                 CASE (CEE_REM_UN) ves_abort(); BREAK;
1296                 CASE (CEE_AND)
1297                         ++ip;
1298                         --sp;
1299                         if (sp->type == VAL_I32)
1300                                 sp [-1].data.i &= GET_NATI (sp [0]);
1301                         else if (sp->type == VAL_I64)
1302                                 sp [-1].data.l &= sp [0].data.l;
1303                         else
1304                                 GET_NATI (sp [-1]) &= GET_NATI (sp [0]);
1305                         BREAK;
1306                 CASE (CEE_OR)
1307                         ++ip;
1308                         --sp;
1309                         if (sp->type == VAL_I32)
1310                                 sp [-1].data.i |= GET_NATI (sp [0]);
1311                         else if (sp->type == VAL_I64)
1312                                 sp [-1].data.l |= sp [0].data.l;
1313                         else
1314                                 GET_NATI (sp [-1]) |= GET_NATI (sp [0]);
1315                         BREAK;
1316                 CASE (CEE_XOR)
1317                         ++ip;
1318                         --sp;
1319                         if (sp->type == VAL_I32)
1320                                 sp [-1].data.i ^= GET_NATI (sp [0]);
1321                         else if (sp->type == VAL_I64)
1322                                 sp [-1].data.l ^= sp [0].data.l;
1323                         else
1324                                 GET_NATI (sp [-1]) ^= GET_NATI (sp [0]);
1325                         BREAK;
1326                 CASE (CEE_SHL)
1327                         ++ip;
1328                         --sp;
1329                         if (sp->type == VAL_I32)
1330                                 sp [-1].data.i <<= GET_NATI (sp [0]);
1331                         else if (sp->type == VAL_I64)
1332                                 sp [-1].data.l <<= GET_NATI (sp [0]);
1333                         else
1334                                 GET_NATI (sp [-1]) <<= GET_NATI (sp [0]);
1335                         BREAK;
1336                 CASE (CEE_SHR)
1337                         ++ip;
1338                         --sp;
1339                         if (sp->type == VAL_I32)
1340                                 sp [-1].data.i >>= GET_NATI (sp [0]);
1341                         else if (sp->type == VAL_I64)
1342                                 sp [-1].data.l >>= GET_NATI (sp [0]);
1343                         else
1344                                 GET_NATI (sp [-1]) >>= GET_NATI (sp [0]);
1345                         BREAK;
1346                 CASE (CEE_SHR_UN) ves_abort(); BREAK;
1347                 CASE (CEE_NEG)
1348                         ++ip;
1349                         if (sp->type == VAL_I32)
1350                                 sp->data.i = - sp->data.i;
1351                         else if (sp->type == VAL_I64)
1352                                 sp->data.l = - sp->data.l;
1353                         else if (sp->type == VAL_DOUBLE)
1354                                 sp->data.f = - sp->data.f;
1355                         else if (sp->type == VAL_NATI)
1356                                 sp->data.p = (gpointer)(- (m_i)sp->data.p);
1357                         BREAK;
1358                 CASE (CEE_NOT)
1359                         ++ip;
1360                         if (sp->type == VAL_I32)
1361                                 sp->data.i = ~ sp->data.i;
1362                         else if (sp->type == VAL_I64)
1363                                 sp->data.l = ~ sp->data.l;
1364                         else if (sp->type == VAL_NATI)
1365                                 sp->data.p = (gpointer)(~ (m_i)sp->data.p);
1366                         BREAK;
1367                 CASE (CEE_CONV_I1) ves_abort(); BREAK;
1368                 CASE (CEE_CONV_I2) ves_abort(); BREAK;
1369                 CASE (CEE_CONV_I4) {
1370                         ++ip;
1371                         /* FIXME: handle other cases. what about sign? */
1372
1373                         switch (sp [-1].type) {
1374                         case VAL_DOUBLE:
1375                                 sp [-1].data.i = (gint32)sp [-1].data.f;
1376                                 sp [-1].type = VAL_I32;
1377                                 break;
1378                         case VAL_I32:
1379                                 break;
1380                         default:
1381                                 ves_abort();
1382                         }
1383                         BREAK;
1384                 }
1385                 CASE (CEE_CONV_I8) ves_abort(); BREAK;
1386                 CASE (CEE_CONV_R4) ves_abort(); BREAK;
1387                 CASE (CEE_CONV_R8)
1388                         ++ip;
1389                         /* FIXME: handle other cases. what about sign? */
1390                         if (sp [-1].type == VAL_I32) {
1391                                 sp [-1].data.f = (double)sp [-1].data.i;
1392                                 sp [-1].type = VAL_DOUBLE;
1393                         } else {
1394                                 ves_abort();
1395                         }
1396                         BREAK;
1397                 CASE (CEE_CONV_U4)
1398                         ++ip;
1399                         /* FIXME: handle other cases. what about sign? */
1400                         if (sp [-1].type == VAL_DOUBLE) {
1401                                 sp [-1].data.i = (guint32)sp [-1].data.f;
1402                                 sp [-1].type = VAL_I32;
1403                         } else {
1404                                 ves_abort();
1405                         }
1406                         BREAK;
1407                 CASE (CEE_CONV_U) 
1408                         ++ip;
1409                         /* FIXME: handle other cases */
1410                         if (sp [-1].type == VAL_I32) {
1411                                 /* defined as NOP */
1412                         } else {
1413                                 ves_abort();
1414                         }
1415                         BREAK;
1416                 CASE (CEE_CONV_U8) ves_abort(); BREAK;
1417                 CASE (CEE_CPOBJ) ves_abort(); BREAK;
1418                 CASE (CEE_LDOBJ) ves_abort(); BREAK;
1419                 CASE (CEE_LDSTR) {
1420                         guint32 ctor, ttoken;
1421                         MonoMetadata *m = &image->metadata;
1422                         MonoObject *o;
1423                         MonoImage *cl;
1424                         const char *name;
1425                         int len;
1426                         guint32 index;
1427                         guint16 *data;
1428
1429                         ip++;
1430                         index = mono_metadata_token_index (read32 (ip));
1431                         ip += 4;
1432
1433                         name = mono_metadata_user_string (m, index);
1434                         len = mono_metadata_decode_blob_size (name, &name);
1435                         /* 
1436                          * terminate with 0, maybe we should use another 
1437                          * constructor and pass the len
1438                          */
1439                         data = g_malloc (len + 2);
1440                         memcpy (data, name, len + 2);
1441                         data [len/2 + 1] = 0;
1442
1443                         ctor = mono_get_string_class_info (&ttoken, &cl);
1444                         o = mono_object_new (cl, ttoken);
1445                         
1446                         g_assert (o != NULL);
1447
1448                         child_frame.method = mono_get_method (cl, ctor);
1449
1450                         child_frame.obj = o;
1451                         
1452                         sp->type = VAL_TP;
1453                         sp->data.p = data;
1454                         
1455                         child_frame.stack_args = sp;
1456
1457                         g_assert (child_frame.method->signature->call_convention == MONO_CALL_DEFAULT);
1458                         ves_exec_method (&child_frame);
1459
1460                         g_free (data);
1461
1462                         sp->type = VAL_OBJ;
1463                         sp->data.p = o;
1464                         ++sp;
1465                         BREAK;
1466                 }
1467                 CASE (CEE_NEWOBJ) {
1468                         MonoObject *o;
1469                         MonoMethodSignature *csig;
1470                         guint32 token;
1471
1472                         ip++;
1473                         token = read32 (ip);
1474                         o = newobj (image, token);
1475                         ip += 4;
1476                         
1477                         /* call the contructor */
1478                         child_frame.method = mono_get_method (image, token);
1479                         csig = child_frame.method->signature;
1480
1481                         /*
1482                          * First arg is the object.
1483                          */
1484                         child_frame.obj = o;
1485
1486                         if (csig->param_count) {
1487                                 sp -= csig->param_count;
1488                                 child_frame.stack_args = sp;
1489                         } else {
1490                                 child_frame.stack_args = NULL;
1491                         }
1492
1493                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
1494
1495                         ves_exec_method (&child_frame);
1496                         /*
1497                          * FIXME: check for exceptions
1498                          */
1499                         /*
1500                          * a constructor returns void, but we need to return the object we created
1501                          */
1502                         sp->type = VAL_OBJ;
1503                         sp->data.p = o;
1504                         ++sp;
1505                         BREAK;
1506                 }
1507                 CASE (CEE_CASTCLASS) {
1508                         MonoObject *o;
1509                         MonoClass *c;
1510                         guint32 token;
1511                         gboolean found = FALSE;
1512
1513                         ++ip;
1514                         token = read32 (ip);
1515
1516                         g_assert (sp [-1].type == VAL_OBJ);
1517
1518                         if ((o = sp [-1].data.p)) {
1519                                 c = o->klass;
1520
1521                                 /* 
1522                                  * fixme: this only works for class casts, but not for 
1523                                  * interface casts. 
1524                                  */
1525                                 while (c) {
1526                                         if (c->type_token == token) {
1527                                                 found = TRUE;
1528                                                 break;
1529                                         }
1530                                         c = c->parent;
1531                                 }
1532
1533                                 g_assert (found);
1534
1535                         }
1536
1537                         ip += 4;
1538                         BREAK;
1539                 }
1540                 CASE (CEE_ISINST) ves_abort(); BREAK;
1541                 CASE (CEE_CONV_R_UN) ves_abort(); BREAK;
1542                 CASE (CEE_UNUSED58) ves_abort(); BREAK;
1543                 CASE (CEE_UNUSED1) ves_abort(); BREAK;
1544                 CASE (CEE_UNBOX) {
1545                         MonoObject *o;
1546                         MonoClass *c;
1547                         guint32 token;
1548
1549                         ++ip;
1550                         token = read32 (ip);
1551                         
1552                         c = mono_class_get (image, token);
1553                         
1554                         o = sp [-1].data.p;
1555
1556                         g_assert (o->klass->type_token == c->type_token);
1557
1558                         sp [-1].type = VAL_MP;
1559                         sp [-1].data.p = (char *)o + sizeof (MonoObject);
1560
1561                         ip += 4;
1562                         BREAK;
1563                 }
1564                 CASE (CEE_THROW)
1565                         --sp;
1566                         THROW_EX (sp->data.p, ip);
1567                         BREAK;
1568                 CASE (CEE_LDFLD) {
1569                         MonoObject *obj;
1570                         MonoClassField *field;
1571                         guint32 token;
1572
1573                         ++ip;
1574                         token = read32 (ip);
1575                         ip += 4;
1576                         
1577                         g_assert (sp [-1].type == VAL_OBJ);
1578                         obj = sp [-1].data.p;
1579                         field = mono_class_get_field (obj->klass, token);
1580                         g_assert (field);
1581                         sp [-1] = stackval_from_data (field->type->type, (char*)obj + field->offset);
1582                         BREAK;
1583                 }
1584                 CASE (CEE_LDFLDA) ves_abort(); BREAK;
1585                 CASE (CEE_STFLD) {
1586                         MonoObject *obj;
1587                         MonoClassField *field;
1588                         guint32 token;
1589
1590                         ++ip;
1591                         token = read32 (ip);
1592                         ip += 4;
1593                         
1594                         sp -= 2;
1595                         
1596                         g_assert (sp [0].type == VAL_OBJ);
1597                         obj = sp [0].data.p;
1598                         field = mono_class_get_field (obj->klass, token);
1599                         g_assert (field);
1600                         stackval_to_data (field->type->type, &sp [1], (char*)obj + field->offset);
1601                         BREAK;
1602                 }
1603                 CASE (CEE_LDSFLD) {
1604                         MonoClass *klass;
1605                         MonoClassField *field;
1606                         guint32 token;
1607
1608                         ++ip;
1609                         token = read32 (ip);
1610                         ip += 4;
1611                         
1612                         /* need to handle fieldrefs */
1613                         klass = mono_class_get (image, 
1614                                 MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (&image->metadata, token & 0xffffff));
1615                         field = mono_class_get_field (klass, token);
1616                         g_assert (field);
1617                         *sp = stackval_from_data (field->type->type, (char*)klass + field->offset);
1618                         ++sp;
1619                         BREAK;
1620                 }
1621                 CASE (CEE_LDSFLDA) ves_abort(); BREAK;
1622                 CASE (CEE_STSFLD) {
1623                         MonoClass *klass;
1624                         MonoClassField *field;
1625                         guint32 token;
1626
1627                         ++ip;
1628                         token = read32 (ip);
1629                         ip += 4;
1630                         --sp;
1631
1632                         /* need to handle fieldrefs */
1633                         klass = mono_class_get (image, 
1634                                 MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (&image->metadata, token & 0xffffff));
1635                         field = mono_class_get_field (klass, token);
1636                         g_assert (field);
1637                         stackval_to_data (field->type->type, sp, (char*)klass + field->offset);
1638                         BREAK;
1639                 }
1640                 CASE (CEE_STOBJ) ves_abort(); BREAK;
1641                 CASE (CEE_CONV_OVF_I1_UN) ves_abort(); BREAK;
1642                 CASE (CEE_CONV_OVF_I2_UN) ves_abort(); BREAK;
1643                 CASE (CEE_CONV_OVF_I4_UN) ves_abort(); BREAK;
1644                 CASE (CEE_CONV_OVF_I8_UN) ves_abort(); BREAK;
1645                 CASE (CEE_CONV_OVF_U1_UN) ves_abort(); BREAK;
1646                 CASE (CEE_CONV_OVF_U2_UN) ves_abort(); BREAK;
1647                 CASE (CEE_CONV_OVF_U4_UN) ves_abort(); BREAK;
1648                 CASE (CEE_CONV_OVF_U8_UN) ves_abort(); BREAK;
1649                 CASE (CEE_CONV_OVF_I_UN) ves_abort(); BREAK;
1650                 CASE (CEE_CONV_OVF_U_UN) ves_abort(); BREAK;
1651                 CASE (CEE_BOX) {
1652                         guint32 token;
1653
1654                         ip++;
1655                         token = read32 (ip);
1656
1657                         sp [-1].type = VAL_OBJ;
1658                         sp [-1].data.p = mono_value_box (image, token, 
1659                                                          &sp [-1]);
1660
1661                         ip += 4;
1662
1663                         BREAK;
1664                 }
1665                 CASE (CEE_NEWARR) {
1666                         MonoObject *o;
1667                         guint32 token;
1668
1669                         ip++;
1670                         token = read32 (ip);
1671                         o = mono_new_szarray (image, token, sp [-1].data.i);
1672                         ip += 4;
1673
1674                         sp [-1].type = VAL_OBJ;
1675                         sp [-1].data.p = o;
1676
1677                         BREAK;
1678                 }
1679                 CASE (CEE_LDLEN) {
1680                         MonoArrayObject *o;
1681
1682                         ip++;
1683
1684                         g_assert (sp [-1].type == VAL_OBJ);
1685
1686                         o = sp [-1].data.p;
1687                         g_assert (o != NULL);
1688                         
1689                         g_assert (MONO_CLASS_IS_ARRAY (o->obj.klass));
1690
1691                         sp [-1].type = VAL_I32;
1692                         sp [-1].data.i = o->bounds [0].length;
1693
1694                         BREAK;
1695                 }
1696                 CASE (CEE_LDELEMA) ves_abort(); BREAK;
1697                 CASE (CEE_LDELEM_I1) /* fall through */
1698                 CASE (CEE_LDELEM_U1) /* fall through */
1699                 CASE (CEE_LDELEM_I2) /* fall through */
1700                 CASE (CEE_LDELEM_U2) /* fall through */
1701                 CASE (CEE_LDELEM_I4) /* fall through */
1702                 CASE (CEE_LDELEM_U4) /* fall through */
1703                 CASE (CEE_LDELEM_I)  /* fall through */
1704                 CASE (CEE_LDELEM_R4) /* fall through */
1705                 CASE (CEE_LDELEM_R8) /* fall through */
1706                 CASE (CEE_LDELEM_REF) {
1707                         MonoArrayObject *o;
1708
1709                         sp -= 2;
1710
1711                         g_assert (sp [0].type == VAL_OBJ);
1712                         o = sp [0].data.p;
1713
1714                         g_assert (MONO_CLASS_IS_ARRAY (o->obj.klass));
1715                         
1716                         g_assert (sp [1].data.i >= 0);
1717                         g_assert (sp [1].data.i < o->bounds [0].length);
1718                         
1719                         switch (*ip) {
1720                         case CEE_LDELEM_I1:
1721                                 sp [0].data.i = ((gint8 *)o->vector)[sp [1].data.i]; 
1722                                 sp [0].type = VAL_I32;
1723                                 break;
1724                         case CEE_LDELEM_U1:
1725                                 sp [0].data.i = ((guint8 *)o->vector)[sp [1].data.i]; 
1726                                 sp [0].type = VAL_I32;
1727                                 break;
1728                         case CEE_LDELEM_I2:
1729                                 sp [0].data.i = ((gint16 *)o->vector)[sp [1].data.i]; 
1730                                 sp [0].type = VAL_I32;
1731                                 break;
1732                         case CEE_LDELEM_U2:
1733                                 sp [0].data.i = ((guint16 *)o->vector)[sp [1].data.i]; 
1734                                 sp [0].type = VAL_I32;
1735                                 break;
1736                         case CEE_LDELEM_I:
1737                                 sp [0].data.i = ((gint32 *)o->vector)[sp [1].data.i]; 
1738                                 sp [0].type = VAL_NATI;
1739                                 break;
1740                         case CEE_LDELEM_I4:
1741                                 sp [0].data.i = ((gint32 *)o->vector)[sp [1].data.i]; 
1742                                 sp [0].type = VAL_I32;
1743                                 break;
1744                         case CEE_LDELEM_U4:
1745                                 sp [0].data.i = ((guint32 *)o->vector)[sp [1].data.i]; 
1746                                 sp [0].type = VAL_I32;
1747                                 break;
1748                         case CEE_LDELEM_R4:
1749                                 sp [0].data.f = ((float *)o->vector)[sp [1].data.i]; 
1750                                 sp [0].type = VAL_DOUBLE;
1751                                 break;
1752                         case CEE_LDELEM_R8:
1753                                 sp [0].data.i = ((double *)o->vector)[sp [1].data.i]; 
1754                                 sp [0].type = VAL_DOUBLE;
1755                                 break;
1756                         case CEE_LDELEM_REF:
1757                                 sp [0].data.p = ((gpointer *)o->vector)[sp [1].data.i]; 
1758                                 sp [0].type = VAL_OBJ;
1759                                 break;
1760                         default:
1761                                 ves_abort();
1762                         }
1763
1764                         ++ip;
1765                         ++sp;
1766
1767                         BREAK;
1768                 }
1769                 CASE (CEE_LDELEM_I8) ves_abort(); BREAK;
1770                 CASE (CEE_STELEM_I)  /* fall through */
1771                 CASE (CEE_STELEM_I1) /* fall through */ 
1772                 CASE (CEE_STELEM_I2) /* fall through */
1773                 CASE (CEE_STELEM_I4) /* fall through */
1774                 CASE (CEE_STELEM_R4) /* fall through */
1775                 CASE (CEE_STELEM_R8) /* fall through */
1776                 CASE (CEE_STELEM_REF) {
1777                         MonoArrayObject *o;
1778                         MonoArrayClass *ac;
1779                         MonoObject *v;
1780
1781                         sp -= 3;
1782
1783                         g_assert (sp [0].type == VAL_OBJ);
1784                         o = sp [0].data.p;
1785
1786                         g_assert (MONO_CLASS_IS_ARRAY (o->obj.klass));
1787                         ac = (MonoArrayClass *)o->obj.klass;
1788                     
1789                         g_assert (sp [1].data.i >= 0);
1790                         g_assert (sp [1].data.i < o->bounds [0].length);
1791
1792                         switch (*ip) {
1793                         case CEE_STELEM_I:
1794                                 ((gint32 *)o->vector)[sp [1].data.i] = 
1795                                         sp [2].data.i;
1796                                 break;
1797                         case CEE_STELEM_I1:
1798                                 ((gint8 *)o->vector)[sp [1].data.i] = 
1799                                         sp [2].data.i;
1800                                 break;
1801                         case CEE_STELEM_I2:
1802                                 ((gint16 *)o->vector)[sp [1].data.i] = 
1803                                         sp [2].data.i;
1804                                 break;
1805                         case CEE_STELEM_I4:
1806                                 ((gint32 *)o->vector)[sp [1].data.i] = 
1807                                         sp [2].data.i;
1808                                 break;
1809                         case CEE_STELEM_R4:
1810                                 ((float *)o->vector)[sp [1].data.i] = 
1811                                         sp [2].data.f;
1812                                 break;
1813                         case CEE_STELEM_R8:
1814                                 ((double *)o->vector)[sp [1].data.i] = 
1815                                         sp [2].data.f;
1816                                 break;
1817                         case CEE_STELEM_REF:
1818                                 g_assert (sp [2].type == VAL_OBJ);
1819                         
1820                                 v = sp [2].data.p;
1821
1822                                 //fixme: what about type conversions ?
1823                                 g_assert (v->klass->type_token == ac->etype_token);
1824
1825                                 ((gpointer *)o->vector)[sp [1].data.i] = 
1826                                         sp [2].data.p;
1827                                 break;
1828                         default:
1829                                 ves_abort();
1830                         }
1831
1832                         ++ip;
1833
1834                         BREAK;
1835                 }
1836                 CASE (CEE_STELEM_I8)  ves_abort(); BREAK;
1837                 CASE (CEE_UNUSED2) 
1838                 CASE (CEE_UNUSED3) 
1839                 CASE (CEE_UNUSED4) 
1840                 CASE (CEE_UNUSED5) 
1841                 CASE (CEE_UNUSED6) 
1842                 CASE (CEE_UNUSED7) 
1843                 CASE (CEE_UNUSED8) 
1844                 CASE (CEE_UNUSED9) 
1845                 CASE (CEE_UNUSED10) 
1846                 CASE (CEE_UNUSED11) 
1847                 CASE (CEE_UNUSED12) 
1848                 CASE (CEE_UNUSED13) 
1849                 CASE (CEE_UNUSED14) 
1850                 CASE (CEE_UNUSED15) 
1851                 CASE (CEE_UNUSED16) 
1852                 CASE (CEE_UNUSED17) ves_abort(); BREAK;
1853                 CASE (CEE_CONV_OVF_I1) ves_abort(); BREAK;
1854                 CASE (CEE_CONV_OVF_U1) ves_abort(); BREAK;
1855                 CASE (CEE_CONV_OVF_I2) ves_abort(); BREAK;
1856                 CASE (CEE_CONV_OVF_U2) ves_abort(); BREAK;
1857                 CASE (CEE_CONV_OVF_I4) ves_abort(); BREAK;
1858                 CASE (CEE_CONV_OVF_U4)
1859                         ++ip;
1860                         /* FIXME: handle other cases */
1861                         if (sp [-1].type == VAL_I32) {
1862                                 /* defined as NOP */
1863                         } else {
1864                                 ves_abort();
1865                         }
1866                         BREAK;
1867                 CASE (CEE_CONV_OVF_I8) ves_abort(); BREAK;
1868                 CASE (CEE_CONV_OVF_U8) ves_abort(); BREAK;
1869                 CASE (CEE_UNUSED50) 
1870                 CASE (CEE_UNUSED18) 
1871                 CASE (CEE_UNUSED19) 
1872                 CASE (CEE_UNUSED20) 
1873                 CASE (CEE_UNUSED21) 
1874                 CASE (CEE_UNUSED22) 
1875                 CASE (CEE_UNUSED23) ves_abort(); BREAK;
1876                 CASE (CEE_REFANYVAL) ves_abort(); BREAK;
1877                 CASE (CEE_CKFINITE) ves_abort(); BREAK;
1878                 CASE (CEE_UNUSED24) ves_abort(); BREAK;
1879                 CASE (CEE_UNUSED25) ves_abort(); BREAK;
1880                 CASE (CEE_MKREFANY) ves_abort(); BREAK;
1881                 CASE (CEE_UNUSED59) 
1882                 CASE (CEE_UNUSED60) 
1883                 CASE (CEE_UNUSED61) 
1884                 CASE (CEE_UNUSED62) 
1885                 CASE (CEE_UNUSED63) 
1886                 CASE (CEE_UNUSED64) 
1887                 CASE (CEE_UNUSED65) 
1888                 CASE (CEE_UNUSED66) 
1889                 CASE (CEE_UNUSED67) ves_abort(); BREAK;
1890                 CASE (CEE_LDTOKEN) ves_abort(); BREAK;
1891                 CASE (CEE_CONV_U2) ves_abort(); BREAK;
1892                 CASE (CEE_CONV_U1) ves_abort(); BREAK;
1893                 CASE (CEE_CONV_I) ves_abort(); BREAK;
1894                 CASE (CEE_CONV_OVF_I) ves_abort(); BREAK;
1895                 CASE (CEE_CONV_OVF_U) ves_abort(); BREAK;
1896                 CASE (CEE_ADD_OVF) ves_abort(); BREAK;
1897                 CASE (CEE_ADD_OVF_UN) ves_abort(); BREAK;
1898                 CASE (CEE_MUL_OVF) ves_abort(); BREAK;
1899                 CASE (CEE_MUL_OVF_UN) ves_abort(); BREAK;
1900                 CASE (CEE_SUB_OVF) ves_abort(); BREAK;
1901                 CASE (CEE_SUB_OVF_UN) ves_abort(); BREAK;
1902                 CASE (CEE_ENDFINALLY)
1903                         if (frame->ex)
1904                                 goto handle_fault;
1905                         /*
1906                          * There was no exception, we continue normally at the target address.
1907                          */
1908                         ip = endfinally_ip;
1909                         BREAK;
1910                 CASE (CEE_LEAVE) ves_abort(); BREAK;
1911                 CASE (CEE_LEAVE_S)
1912                         ++ip;
1913                         ip += (signed char) *ip;
1914                         /*
1915                          * We may be either inside a try block or inside an handler.
1916                          * In the first case there was no exception and we go on
1917                          * executing the finally handlers and after that resume control
1918                          * at endfinally_ip.
1919                          * In the second case we need to clear the exception and
1920                          * continue directly at the target ip.
1921                          */
1922                         if (frame->ex) {
1923                                 frame->ex = NULL;
1924                                 frame->ex_handler = NULL;
1925                         } else {
1926                                 endfinally_ip = ip;
1927                                 goto handle_finally;
1928                         }
1929                         BREAK;
1930                 CASE (CEE_STIND_I) ves_abort(); BREAK;
1931                 CASE (CEE_UNUSED26) 
1932                 CASE (CEE_UNUSED27) 
1933                 CASE (CEE_UNUSED28) 
1934                 CASE (CEE_UNUSED29) 
1935                 CASE (CEE_UNUSED30) 
1936                 CASE (CEE_UNUSED31) 
1937                 CASE (CEE_UNUSED32) 
1938                 CASE (CEE_UNUSED33) 
1939                 CASE (CEE_UNUSED34) 
1940                 CASE (CEE_UNUSED35) 
1941                 CASE (CEE_UNUSED36) 
1942                 CASE (CEE_UNUSED37) 
1943                 CASE (CEE_UNUSED38) 
1944                 CASE (CEE_UNUSED39) 
1945                 CASE (CEE_UNUSED40) 
1946                 CASE (CEE_UNUSED41) 
1947                 CASE (CEE_UNUSED42) 
1948                 CASE (CEE_UNUSED43) 
1949                 CASE (CEE_UNUSED44) 
1950                 CASE (CEE_UNUSED45) 
1951                 CASE (CEE_UNUSED46) 
1952                 CASE (CEE_UNUSED47) 
1953                 CASE (CEE_UNUSED48) ves_abort(); BREAK;
1954                 CASE (CEE_PREFIX7) ves_abort(); BREAK;
1955                 CASE (CEE_PREFIX6) ves_abort(); BREAK;
1956                 CASE (CEE_PREFIX5) ves_abort(); BREAK;
1957                 CASE (CEE_PREFIX4) ves_abort(); BREAK;
1958                 CASE (CEE_PREFIX3) ves_abort(); BREAK;
1959                 CASE (CEE_PREFIX2) ves_abort(); BREAK;
1960                 CASE (CEE_PREFIXREF) ves_abort(); BREAK;
1961                 SUB_SWITCH
1962                         ++ip;
1963                         switch (*ip) {
1964                         case CEE_ARGLIST: ves_abort(); break;
1965                         case CEE_CEQ: ves_abort(); break;
1966                         case CEE_CGT: ves_abort(); break;
1967                         case CEE_CGT_UN: ves_abort(); break;
1968                         case CEE_CLT: ves_abort(); break;
1969                         case CEE_CLT_UN: ves_abort(); break;
1970                         case CEE_LDFTN: ves_abort(); break;
1971                         case CEE_LDVIRTFTN: ves_abort(); break;
1972                         case CEE_UNUSED56: ves_abort(); break;
1973                         case CEE_LDARG: ves_abort(); break;
1974                         case CEE_LDARGA: ves_abort(); break;
1975                         case CEE_STARG: ves_abort(); break;
1976                         case CEE_LDLOC: ves_abort(); break;
1977                         case CEE_LDLOCA: ves_abort(); break;
1978                         case CEE_STLOC: ves_abort(); break;
1979                         case CEE_LOCALLOC: ves_abort(); break;
1980                         case CEE_UNUSED57: ves_abort(); break;
1981                         case CEE_ENDFILTER: ves_abort(); break;
1982                         case CEE_UNALIGNED_: ves_abort(); break;
1983                         case CEE_VOLATILE_: ves_abort(); break;
1984                         case CEE_TAIL_: ves_abort(); break;
1985                         case CEE_INITOBJ: ves_abort(); break;
1986                         case CEE_UNUSED68: ves_abort(); break;
1987                         case CEE_CPBLK: ves_abort(); break;
1988                         case CEE_INITBLK: ves_abort(); break;
1989                         case CEE_UNUSED69: ves_abort(); break;
1990                         case CEE_RETHROW: ves_abort(); break;
1991                         case CEE_UNUSED: ves_abort(); break;
1992                         case CEE_SIZEOF: ves_abort(); break;
1993                         case CEE_REFANYTYPE: ves_abort(); break;
1994                         case CEE_UNUSED52: 
1995                         case CEE_UNUSED53: 
1996                         case CEE_UNUSED54: 
1997                         case CEE_UNUSED55: 
1998                         case CEE_UNUSED70: 
1999                         default:
2000                                 g_error ("Unimplemented opcode: 0xFE %02x at 0x%x\n", *ip, ip-header->code);
2001                         }
2002                         continue;
2003                 DEFAULT;
2004                 }
2005         }
2006
2007         g_assert_not_reached ();
2008         /*
2009          * Exception handling code.
2010          * The exception object is stored in frame->ex.
2011          */
2012 #define OFFSET_IN_CLAUSE(clause,offset) \
2013         ((clause)->try_offset <= (offset) && (offset) < ((clause)->try_offset + (clause)->try_len))
2014
2015         handle_exception:
2016         {
2017                 int i;
2018                 guint32 ip_offset;
2019                 MonoInvocation *inv;
2020                 MonoMethodHeader *hd;
2021                 MonoExceptionClause *clause;
2022                 
2023                 for (inv = frame; inv; inv = inv->parent) {
2024                         hd = ((MonoMethodNormal*)inv->method)->header;
2025                         ip_offset = inv->ip - hd->code;
2026                         for (i = 0; i < hd->num_clauses; ++i) {
2027                                 clause = &hd->clauses [i];
2028                                 if (clause->flags <= 1 && OFFSET_IN_CLAUSE (clause, ip_offset)) {
2029                                         if (!clause->flags && mono_isinst (frame->ex, mono_class_get (inv->method->image, clause->token_or_filter))) {
2030                                                         /* 
2031                                                          * OK, we found an handler, now we need to execute the finally
2032                                                          * and fault blocks before branching to the handler code.
2033                                                          */
2034                                                         inv->ex_handler = clause;
2035                                                         goto handle_finally;
2036                                         } else {
2037                                                 /* FIXME: handle filter clauses */
2038                                                 g_assert (0);
2039                                         }
2040                                 }
2041                         }
2042                 }
2043                 /*
2044                  * If we get here, no handler was found: print a stack trace.
2045                  */
2046                 for (inv = frame, i = 0; inv; inv = inv->parent, ++i) {
2047                         /*
2048                          * FIXME: print out also the arguments passed to the func.
2049                          */
2050                         g_print ("Unhandled exception.\n");
2051                         g_print ("$%d: %s ()\n", i, inv->method->name);
2052                 }
2053                 exit (1);
2054         }
2055         handle_finally:
2056         {
2057                 int i;
2058                 guint32 ip_offset;
2059                 MonoExceptionClause *clause;
2060                 
2061                 ip_offset = frame->ip - header->code;
2062                 for (i = 0; i < header->num_clauses; ++i) {
2063                         clause = &header->clauses [i];
2064                         if (clause->flags == 2 && OFFSET_IN_CLAUSE (clause, ip_offset)) {
2065                                 ip = header->code + clause->handler_offset;
2066                                 goto main_loop;
2067                         }
2068                 }
2069                 /*
2070                  * If an exception is set, we need to execute the fault handler, too,
2071                  * otherwise, we continue normally.
2072                  */
2073                 if (frame->ex)
2074                         goto handle_fault;
2075                 ip = endfinally_ip;
2076                 goto main_loop;
2077         }
2078         handle_fault:
2079         {
2080                 int i;
2081                 guint32 ip_offset;
2082                 MonoExceptionClause *clause;
2083                 
2084                 ip_offset = frame->ip - header->code;
2085                 for (i = 0; i < header->num_clauses; ++i) {
2086                         clause = &header->clauses [i];
2087                         if (clause->flags == 3 && OFFSET_IN_CLAUSE (clause, ip_offset)) {
2088                                 ip = header->code + clause->handler_offset;
2089                                 goto main_loop;
2090                         }
2091                 }
2092                 /*
2093                  * If the handler for the exception was found in this method, we jump
2094                  * to it right away, otherwise we return and let the caller run
2095                  * the finally, fault and catch blocks.
2096                  * This same code should be present in the endfault opcode, but it
2097                  * is corrently not assigned in the ECMA specs: LAMESPEC.
2098                  */
2099                 if (frame->ex_handler) {
2100                         ip = header->code + frame->ex_handler->handler_offset;
2101                         sp = frame->stack;
2102                         sp->type = VAL_OBJ;
2103                         sp->data.p = frame->ex;
2104                         goto main_loop;
2105                 }
2106 #if DEBUG_INTERP
2107                 debug_indent_level--;
2108 #endif
2109                 return;
2110         }
2111         
2112 }
2113
2114 static int 
2115 ves_exec (MonoAssembly *assembly)
2116 {
2117         MonoImage *image = assembly->image;
2118         MonoCLIImageInfo *iinfo;
2119         stackval result;
2120         MonoInvocation call;
2121
2122         iinfo = image->image_info;
2123         
2124         call.parent = NULL;
2125         call.obj = NULL;
2126         call.stack_args = NULL;
2127         call.method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point);
2128         call.retval = &result;
2129         ves_exec_method (&call);
2130         mono_free_method (call.method);
2131
2132         return result.data.i;
2133 }
2134
2135 static void
2136 usage (void)
2137 {
2138         fprintf (stderr, "Usage is: mono-int executable args...");
2139         exit (1);
2140 }
2141
2142 int 
2143 main (int argc, char *argv [])
2144 {
2145         MonoAssembly *assembly;
2146         int retval = 0;
2147         char *file;
2148
2149         if (argc < 2)
2150                 usage ();
2151
2152         file = argv [1];
2153
2154         corlib = mono_get_corlib ();
2155
2156         assembly = mono_assembly_open (file, NULL, NULL);
2157         if (!assembly){
2158                 fprintf (stderr, "Can not open image %s\n", file);
2159                 exit (1);
2160         }
2161         retval = ves_exec (assembly);
2162         mono_assembly_close (assembly);
2163
2164         return retval;
2165 }
2166
2167
2168