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