Initial revision
[cacao.git] / comp / parse.c
1 /****************************** comp/parse.c ***********************************
2
3         Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
4
5         See file COPYRIGHT for information on usage and disclaimer of warranties
6
7         Enth"alt den Parser f"ur die Bytecode-Darstellung der Methoden
8         
9         Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
10                  Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
11
12         Last Change: 1997/10/17
13
14 *******************************************************************************/
15
16
17 /* Kurzschreibweise f"ur oft verwendete Funktionen */
18
19 #define LOADCONST_I  pcmd_loadconst_i
20 #define LOADCONST_L  pcmd_loadconst_l
21 #define LOADCONST_F  pcmd_loadconst_f
22 #define LOADCONST_D  pcmd_loadconst_d
23 #define LOADCONST_A  pcmd_loadconst_a
24 #define MOVE         pcmd_move
25 #define IINC         pcmd_iinc
26 #define OP           pcmd_op
27 #define MEM          pcmd_mem
28 #define BRA          pcmd_bra
29 #define TABLEJUMP    pcmd_tablejump
30 #define METHOD       pcmd_method
31
32 #define BUILTIN1     pcmd_builtin1
33 #define BUILTIN2     pcmd_builtin2
34 #define BUILTIN3     pcmd_builtin3
35
36 #define DROP         pcmd_drop
37 #define ACTIVATE     pcmd_activate
38 #define BRA_N_DROP   pcmd_bra_n_drop
39 #define MOVE_N_DROP  pcmd_move_n_drop
40
41 #define OP1(opcode,s,d)         OP(opcode,s,NOVAR,NOVAR,d)
42 #define OP2(opcode,s1,s2,d)     OP(opcode,s1,s2,NOVAR,d)
43 #define OP3(opcode,s1,s2,s3,d)  OP(opcode,s1,s2,s3,d)
44
45
46 #define EXCREATOR(exclass)      block_createexcreator (exclass, p)
47 #define EXFORWARDER(exvar)      block_createexforwarder (exvar, p)
48
49
50
51
52 /****************** Funktion: addreturnlog ************************************
53
54         f"ugt in den Code einen Aufruf der Methoden-R"uckkehr-Protokollierung
55         ein.
56
57 ******************************************************************************/
58
59 static void addreturnhandling()
60 {
61         if (checksync && (method->flags & ACC_SYNCHRONIZED) ) {
62                 stack_makesaved ();
63 #ifdef USE_THREADS
64                 if (method->flags & ACC_STATIC) {
65                         varid v = var_create (TYPE_ADDRESS);
66                         LOADCONST_A (class, v);
67                         BUILTIN1 ( (functionptr) builtin_monitorexit, v, NOVAR);
68                         } 
69                 else {
70                         BUILTIN1 ( (functionptr) builtin_monitorexit,
71                                     local_get (0, TYPE_ADDRESS) , NOVAR);
72                         }
73 #endif
74                 }
75 }
76
77
78 /*************** Funktion: addreturnexceptionlog *****************************
79
80         f"ugt in den Code einen Aufruf der Methoden-R"uckkehr-Protokollierung
81         mit Exception ein.
82
83 ******************************************************************************/
84
85 static void addreturnexceptionhandling()
86 {
87
88         if (runverbose) {
89                 varid v;
90
91                 stack_makesaved ();
92                 v = var_create (TYPE_ADDRESS);
93                 LOADCONST_A (method, v);
94                 BUILTIN1 ( (functionptr) builtin_displaymethodexception, v, NOVAR);
95                 }
96                 
97         if (checksync && (method->flags & ACC_SYNCHRONIZED) ) {
98                 stack_makesaved ();
99 #ifdef USE_THREADS
100                 if (method->flags & ACC_STATIC) {
101                         varid v = var_create (TYPE_ADDRESS);
102                         LOADCONST_A (class, v);
103                         BUILTIN1 ( (functionptr) builtin_monitorexit, v, NOVAR);
104                         } 
105                 else {
106                         BUILTIN1 ( (functionptr) builtin_monitorexit,
107                                     local_get (0, TYPE_ADDRESS) , NOVAR);
108                         }
109 #endif
110                 }
111 }
112
113
114
115 /******************************************************************************
116 *************** Funktion 'parse' zum Durcharbeiten des Bytecodes **************
117 ******************************************************************************/
118
119 static void parse (basicblock *b)
120 {
121         varid v,v1,v2,v3,ve;
122         u4 poolindex;
123         s4 type;
124         u4 p,i;
125         basicblock *target=NULL;
126         bool iswide=false;
127
128         stack_restore (b->stack);
129         subroutine_set (b->subroutine);
130
131
132         switch (b->type) {
133
134                 /* Code fuer einen Exception-Forwarder generieren */
135
136
137         case BLOCKTYPE_EXFORWARDER:
138                 if (!compileall) {
139                         ACTIVATE (b->exvar);
140                         stack_repush (b->exvar);
141                         stack_makesaved ();
142
143                         for (i=0; i<exceptiontablelength; i++) {
144                                 target = block_find (extable[i].handlerpc);
145                                 if (   extable[i].startpc <= b->throwpos
146                                     && extable[i].endpc > b->throwpos) {
147
148                                         if (!extable[i].catchtype) goto exceptionfits;
149
150                                         stack_makesaved();
151                                         v1 = var_create (TYPE_ADDRESS);
152                                         v2 = var_create (TYPE_ADDRESS);
153                                         v = var_create (TYPE_INT);
154                                         MOVE (TYPE_ADDRESS, b->exvar, v1);
155                                         LOADCONST_A (extable[i].catchtype, v2);
156                                         BUILTIN2 ((functionptr) builtin_instanceof, v1,v2, v);
157
158                                         block_reach (target);
159                                         BRA_N_DROP (CMD_IFNE, v,NOVAR, NOVAR, target);
160                                         }
161                                 }
162                         target = NULL;
163                         }
164                 goto exceptionfits;
165
166
167                 /* Code fuer einen Exception-Creator generieren */
168         case BLOCKTYPE_EXCREATOR:
169                 if (!compileall) {
170                         java_objectheader *o = b->exproto;
171                         LOADCONST_A (o, stack_push(TYPE_ADDRESS) );
172
173                         for (i=0; i<exceptiontablelength; i++) {
174                                 target = block_find (extable[i].handlerpc);
175                                 if (   extable[i].startpc <= b->throwpos
176                                     && extable[i].endpc > b->throwpos) {
177
178                                         if (!extable[i].catchtype) goto exceptionfits;
179                                         if (builtin_instanceof (o, extable[i].catchtype) ) goto exceptionfits;
180                                         }
181                                 }
182                         target = NULL;
183                         }
184
185                 /*** Der Sprung zum Exception-Handler (oder Methodenbeendigung) ***/
186
187           exceptionfits:
188                 if (!compileall) {
189                         if (target) {
190                                 block_reach (target);
191                                 BRA (CMD_GOTO, NOVAR,NOVAR,NOVAR, target);
192                                 goto cleanup;
193                                 }
194
195 #ifdef STATISTICS
196         count_pcmd_returnx++;
197 #endif
198
199                         switch (mreturntype) {
200                                 case TYPE_INT:
201                                         addreturnexceptionhandling();
202
203                                         v1 = var_create (TYPE_INT);
204                                         LOADCONST_I (0, v1);
205                                         BRA_N_DROP (CMD_IRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
206                                         break;
207                                 case TYPE_LONG:
208                                         addreturnexceptionhandling();
209
210                                         v1 = var_create (TYPE_LONG);
211                                         LOADCONST_I (0, v1);
212                                         BRA_N_DROP (CMD_LRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
213                                         break;
214                                 case TYPE_FLOAT:
215                                         addreturnexceptionhandling();
216
217                                         v1 = var_create (TYPE_FLOAT);
218                                         LOADCONST_F (0.0, v1);
219                                         BRA_N_DROP (CMD_FRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
220                                         break;
221                                 case TYPE_DOUBLE:
222                                         addreturnexceptionhandling();
223
224                                         v1 = var_create (TYPE_DOUBLE);
225                                         LOADCONST_D (0.0, v1);
226                                         BRA_N_DROP (CMD_DRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
227                                         break;
228                                 case TYPE_ADDRESS:
229                                         addreturnexceptionhandling();
230
231                                         v1 = var_create (TYPE_ADDRESS);
232                                         LOADCONST_A (NULL, v1);
233                                         BRA_N_DROP (CMD_ARETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
234                                         break;
235                                 case TYPE_VOID:
236                                         addreturnexceptionhandling();
237
238                                         BRA (CMD_RETURN, NOVAR,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
239                                         break;
240                                 }
241                         }
242                 goto cleanup;
243                 }
244
245
246                 /* Code fuer einen (normalen) JavaVM - Block generieren */
247
248         p = b->jpc;
249
250
251         
252         if ( p==0) {
253                 /* Method call protocolling */
254
255                 if (runverbose) {
256                         stack_makesaved();
257                         pcmd_trace (method);
258                         }
259
260                 /* Synchronization */
261                 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
262                         stack_makesaved();
263 #ifdef USE_THREADS
264                         if (method->flags & ACC_STATIC) {
265                                 varid v = var_create (TYPE_ADDRESS);
266                                 LOADCONST_A (class, v);
267                                 BUILTIN1 ( (functionptr) builtin_monitorenter, v, NOVAR);
268                         } 
269                         else {
270                                 BUILTIN1 ( (functionptr) builtin_monitorenter,
271                                             local_get (0, TYPE_ADDRESS), NOVAR );
272                                 }
273 #endif
274                         }                       
275                 }
276
277         for (;;) {
278                 u1 opcode;
279                 u4 nextp;
280
281                 opcode = code_get_u1 (p);
282                 nextp = p + jcommandsize[opcode];
283
284
285                 count_javainstr++;
286
287
288                 if (showstack) {
289                         printf ("PC: %3d  OPCODE: %3d   Stack: ",(int) p, (int) opcode);
290                         stack_display (stack_get());
291                         printf ("\n");
292                         }
293
294
295                 switch (opcode) {
296
297
298                         /*** Pushing constants onto the stack ***/
299
300                         case CMD_BIPUSH:
301                                 LOADCONST_I (code_get_s1 (p+1), stack_push (TYPE_INT) );
302                                 break;
303
304                         case CMD_SIPUSH:
305                                 LOADCONST_I (code_get_s2 (p+1), stack_push (TYPE_INT) );
306                                 break;
307
308                         case CMD_LDC1:  poolindex = code_get_u1 (p+1);
309                                         goto pushconstantitem;
310                         case CMD_LDC2:
311                         case CMD_LDC2W: poolindex = code_get_u2 (p+1);
312                         pushconstantitem:
313                                 switch (class_constanttype(class, poolindex)) {
314                                         case CONSTANT_Integer:
315                                                 { constant_integer *c;
316                                                 c = class_getconstant (class, poolindex, CONSTANT_Integer);
317                                                 LOADCONST_I (c->value, stack_push(TYPE_INT) );
318                                                 }
319                                                 break;
320                                         case CONSTANT_Long:
321                                                 { constant_long *c;
322                                                 c = class_getconstant (class, poolindex, CONSTANT_Long);
323                                                 LOADCONST_L (c->value, stack_push(TYPE_LONG) );
324                                                 }
325                                                 break;
326                                         case CONSTANT_Float:
327                                                 { constant_float *c;
328                                                 c = class_getconstant (class, poolindex, CONSTANT_Float);
329                                                 LOADCONST_F (c->value, stack_push(TYPE_FLOAT) );
330                                                 }
331                                                 break;
332                                         case CONSTANT_Double:
333                                                 { constant_double *c;
334                                                 c = class_getconstant (class, poolindex, CONSTANT_Double);
335                                                 LOADCONST_D (c->value, stack_push(TYPE_DOUBLE) );
336                                                 }
337                                                 break;
338
339                                         case CONSTANT_String:
340                                                 { unicode *s;
341
342                                                 s = class_getconstant (class, poolindex, CONSTANT_String);
343
344                                                 LOADCONST_A ( literalstring_new (s),
345                                                               stack_push(TYPE_ADDRESS) );
346                                                 }
347                                                 break;
348
349                                         default: panic ("Invalid constant type to push");
350                                         }
351                                 break;
352
353
354                         case CMD_ACONST_NULL:
355                                 LOADCONST_A (0,  stack_push (TYPE_ADDRESS) );
356                                 break;
357
358                         case CMD_ICONST_M1:
359                         case CMD_ICONST_0:
360                         case CMD_ICONST_1:
361                         case CMD_ICONST_2:
362                         case CMD_ICONST_3:
363                         case CMD_ICONST_4:
364                         case CMD_ICONST_5:
365                                 LOADCONST_I (opcode - CMD_ICONST_0, stack_push (TYPE_INT) );
366                                 break;
367
368                         case CMD_LCONST_0:
369                         case CMD_LCONST_1:
370 #if U8_AVAILABLE
371                                 LOADCONST_L (opcode - CMD_LCONST_0, stack_push (TYPE_LONG) );
372 #else
373                                 { u8 v;
374                   v.low = opcode - CMD_LCONST_0;
375                                   v.high = 0;
376                                   LOADCONST_L (v, stack_push(TYPE_LONG) );
377                                 }
378 #endif
379                                 break;
380
381                         case CMD_FCONST_0:
382                         case CMD_FCONST_1:
383                         case CMD_FCONST_2:
384                                 LOADCONST_F (opcode - CMD_FCONST_0, stack_push (TYPE_FLOAT) );
385                                 break;
386
387                         case CMD_DCONST_0:
388                         case CMD_DCONST_1:
389                                 LOADCONST_D (opcode - CMD_DCONST_0, stack_push (TYPE_DOUBLE) );
390                                 break;
391
392
393                         /*** Loading variables onto the Stack ***/
394
395                         case CMD_ILOAD:
396                                 if (!iswide) {
397                                         MOVE ( TYPE_INT,
398                                                local_get (code_get_u1 (p+1), TYPE_INT),
399                                                stack_push (TYPE_INT) );
400                                         }
401                                 else {
402                                         MOVE ( TYPE_INT,
403                                                local_get (code_get_u2 (p+1), TYPE_INT),
404                                                stack_push (TYPE_INT) );
405                                         nextp = p+3;
406                                         iswide = false;
407                                         }
408                                 break;
409
410                         case CMD_ILOAD_0:
411                         case CMD_ILOAD_1:
412                         case CMD_ILOAD_2:
413                         case CMD_ILOAD_3:
414                                 MOVE ( TYPE_INT,
415                                        local_get (opcode - CMD_ILOAD_0, TYPE_INT),
416                                        stack_push (TYPE_INT) );
417                                 break;
418
419                         case CMD_LLOAD:
420                                 if (!iswide) {
421                                         MOVE ( TYPE_LONG,
422                                                local_get (code_get_u1 (p+1), TYPE_LONG),
423                                                stack_push (TYPE_LONG) );
424                                         }
425                                 else {
426                                         MOVE ( TYPE_LONG,
427                                                local_get (code_get_u2 (p+1), TYPE_LONG),
428                                                stack_push (TYPE_LONG) );
429                                         nextp = p+3;
430                                         iswide = false;
431                                         }
432                                 break;
433
434                         case CMD_LLOAD_0:
435                         case CMD_LLOAD_1:
436                         case CMD_LLOAD_2:
437                         case CMD_LLOAD_3:
438                                 MOVE ( TYPE_LONG,
439                                        local_get (opcode - CMD_LLOAD_0, TYPE_LONG),
440                                        stack_push (TYPE_LONG) );
441                                 break;
442
443                         case CMD_FLOAD:
444                                 if (!iswide) {
445                                         MOVE ( TYPE_FLOAT,
446                                                local_get (code_get_u1 (p+1), TYPE_FLOAT),
447                                                stack_push (TYPE_FLOAT) );
448                                         }
449                                 else {
450                                         MOVE ( TYPE_FLOAT,
451                                                local_get (code_get_u2 (p+1), TYPE_FLOAT),
452                                                stack_push (TYPE_FLOAT) );
453                                         nextp = p+3;
454                                         iswide = false;
455                                         }
456                                 break;
457
458                         case CMD_FLOAD_0:
459                         case CMD_FLOAD_1:
460                         case CMD_FLOAD_2:
461                         case CMD_FLOAD_3:
462                                 MOVE ( TYPE_FLOAT,
463                                        local_get (opcode - CMD_FLOAD_0, TYPE_FLOAT),
464                                        stack_push (TYPE_FLOAT) );
465                                 break;
466
467                         case CMD_DLOAD:
468                                 if (!iswide) {
469                                         MOVE ( TYPE_DOUBLE,
470                                                local_get (code_get_u1 (p+1), TYPE_DOUBLE),
471                                                stack_push (TYPE_DOUBLE) );
472                                         }
473                                 else {
474                                         MOVE ( TYPE_DOUBLE,
475                                                local_get (code_get_u2 (p+1), TYPE_DOUBLE),
476                                                stack_push (TYPE_DOUBLE) );
477                                         nextp = p+3;
478                                         iswide = false;
479                                         }
480                                 break;
481
482                         case CMD_DLOAD_0:
483                         case CMD_DLOAD_1:
484                         case CMD_DLOAD_2:
485                         case CMD_DLOAD_3:
486                                 MOVE ( TYPE_DOUBLE,
487                                        local_get (opcode - CMD_DLOAD_0, TYPE_DOUBLE),
488                                        stack_push (TYPE_DOUBLE) );
489                                 break;
490
491                         case CMD_ALOAD:
492                                 if (!iswide) {
493                                         MOVE ( TYPE_ADDRESS,
494                                                local_get (code_get_u1 (p+1), TYPE_ADDRESS),
495                                                stack_push (TYPE_ADDRESS) );
496                                         }
497                                 else {
498                                         MOVE ( TYPE_ADDRESS,
499                                                local_get (code_get_u2 (p+1), TYPE_ADDRESS),
500                                                stack_push (TYPE_ADDRESS) );
501                                         nextp = p+3;
502                                         iswide = false;
503                                         }
504                                 break;
505
506                         case CMD_ALOAD_0:
507                         case CMD_ALOAD_1:
508                         case CMD_ALOAD_2:
509                         case CMD_ALOAD_3:
510                                 MOVE ( TYPE_ADDRESS,
511                                        local_get (opcode - CMD_ALOAD_0, TYPE_ADDRESS),
512                                        stack_push (TYPE_ADDRESS) );
513                                 break;
514
515
516                         /*** Storing Stack Values into Local Variables ***/
517
518                         case CMD_ISTORE:
519                                 v = stack_pop (TYPE_INT);
520                                 if (!iswide) {
521                                         MOVE_N_DROP (TYPE_INT, v,
522                                             local_get (code_get_u1 (p+1), TYPE_INT) );
523                                         }
524                                 else {
525                                         MOVE_N_DROP (TYPE_INT, v,
526                                             local_get (code_get_u2 (p+1), TYPE_INT) );
527                                         iswide=false;
528                                         nextp = p+3;
529                                         }
530                                 break;
531
532                         case CMD_ISTORE_0:
533                         case CMD_ISTORE_1:
534                         case CMD_ISTORE_2:
535                         case CMD_ISTORE_3:
536                                 v = stack_pop (TYPE_INT);
537                                 MOVE_N_DROP (TYPE_INT,
538                                       v, local_get (opcode - CMD_ISTORE_0, TYPE_INT) );
539                                 break;
540
541                         case CMD_LSTORE:
542                                 v = stack_pop (TYPE_LONG);
543                                 if (!iswide) {
544                                         MOVE_N_DROP (TYPE_LONG, v,
545                                             local_get (code_get_u1 (p+1), TYPE_LONG) );
546                                         }
547                                 else {
548                                         MOVE_N_DROP (TYPE_LONG, v,
549                                             local_get (code_get_u2 (p+1), TYPE_LONG) );
550                                         iswide=false;
551                                         nextp = p+3;
552                                         }
553                                 break;
554
555                         case CMD_LSTORE_0:
556                         case CMD_LSTORE_1:
557                         case CMD_LSTORE_2:
558                         case CMD_LSTORE_3:
559                                 v = stack_pop (TYPE_LONG);
560                                 MOVE_N_DROP (TYPE_LONG,
561                                       v, local_get (opcode - CMD_LSTORE_0, TYPE_LONG) );
562                                 break;
563
564                         case CMD_FSTORE:
565                                 v = stack_pop (TYPE_FLOAT);
566                                 if (!iswide) {
567                                         MOVE_N_DROP (TYPE_FLOAT, v,
568                                             local_get (code_get_u1 (p+1), TYPE_FLOAT) );
569                                         }
570                                 else {
571                                         MOVE_N_DROP (TYPE_FLOAT, v,
572                                             local_get (code_get_u2 (p+1), TYPE_FLOAT) );
573                                         iswide=false;
574                                         nextp = p+3;
575                                         }
576                                 break;
577
578                         case CMD_FSTORE_0:
579                         case CMD_FSTORE_1:
580                         case CMD_FSTORE_2:
581                         case CMD_FSTORE_3:
582                                 v = stack_pop (TYPE_FLOAT);
583                                 MOVE_N_DROP (TYPE_FLOAT,
584                                       v, local_get (opcode - CMD_FSTORE_0, TYPE_FLOAT) );
585                                 break;
586
587                         case CMD_DSTORE:
588                                 v = stack_pop (TYPE_DOUBLE);
589                                 if (!iswide) {
590                                         MOVE_N_DROP (TYPE_DOUBLE, v,
591                                             local_get (code_get_u1 (p+1), TYPE_DOUBLE) );
592                                         }
593                                 else {
594                                         MOVE_N_DROP (TYPE_DOUBLE, v,
595                                             local_get (code_get_u2 (p+1), TYPE_DOUBLE) );
596                                         iswide=false;
597                                         nextp = p+3;
598                                         }
599                                 break;
600
601                         case CMD_DSTORE_0:
602                         case CMD_DSTORE_1:
603                         case CMD_DSTORE_2:
604                         case CMD_DSTORE_3:
605                                 v = stack_pop (TYPE_DOUBLE);
606                                 MOVE_N_DROP (TYPE_DOUBLE,
607                                       v, local_get (opcode - CMD_DSTORE_0, TYPE_DOUBLE) );
608                                 break;
609
610                         case CMD_ASTORE:
611                                 v = stack_pop (TYPE_ADDRESS);
612                                 if (!iswide) {
613                                         MOVE_N_DROP (TYPE_ADDRESS, v,
614                                             local_get (code_get_u1 (p+1), TYPE_ADDRESS) );
615                                         }
616                                 else {
617                                         MOVE_N_DROP (TYPE_ADDRESS, v,
618                                             local_get (code_get_u2 (p+1), TYPE_ADDRESS) );
619                                         iswide=false;
620                                         nextp = p+3;
621                                         }
622                                 break;
623
624                         case CMD_ASTORE_0:
625                         case CMD_ASTORE_1:
626                         case CMD_ASTORE_2:
627                         case CMD_ASTORE_3:
628                                 v = stack_pop (TYPE_ADDRESS);
629                                 MOVE_N_DROP (TYPE_ADDRESS,
630                                       v, local_get (opcode - CMD_ASTORE_0, TYPE_ADDRESS) );
631                                 break;
632
633
634                         case CMD_IINC:
635                                 if (!iswide) {
636                                         v1 = local_get (code_get_u1 (p+1), TYPE_INT);
637                                         IINC (code_get_s1 (p+2), v1 );
638                                         DROP (v1);
639                                         }
640                                 else {
641                                         v1 = local_get (code_get_u2 (p+1), TYPE_INT);
642                                         IINC (code_get_s2 (p+3), v1 );
643                                         DROP (v1);
644                                         iswide = false;
645                                         nextp = p+5;
646                                         }
647                                 break;
648
649
650                         /*** Wider index for Loading, Storing and Incrementing ***/
651
652                         case CMD_WIDE:
653                                 iswide=true;
654                                 nextp = p+1;
655                                 break;
656
657
658                         /******************** Managing Arrays **************************/
659
660                         case CMD_NEWARRAY:
661                                 v1 = stack_pop (TYPE_INT);
662                                 BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
663
664                                 stack_makesaved ();
665                                 v = stack_push (TYPE_ADDRESS);
666                                 switch ( code_get_s1 (p+1) ) {
667                                 case 4: BUILTIN1 ((functionptr) builtin_newarray_boolean, v1, v);
668                                             break;
669                                 case 5: BUILTIN1 ((functionptr) builtin_newarray_char, v1, v);
670                                             break;
671                                 case 6: BUILTIN1 ((functionptr) builtin_newarray_float, v1, v);
672                                             break;
673                                 case 7: BUILTIN1 ((functionptr) builtin_newarray_double, v1, v);
674                                             break;
675                                 case 8: BUILTIN1 ((functionptr) builtin_newarray_byte, v1, v);
676                                             break;
677                                 case 9: BUILTIN1 ((functionptr) builtin_newarray_short, v1, v);
678                                             break;
679                                 case 10: BUILTIN1 ((functionptr) builtin_newarray_int, v1, v);
680                                             break;
681                                 case 11: BUILTIN1 ((functionptr) builtin_newarray_long, v1, v);
682                                             break;
683                                 default: panic ("Invalid array-type to create");
684                                 }
685
686                                 BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
687
688                                 break;
689
690                         case CMD_ANEWARRAY:
691                                 poolindex = code_get_u2(p+1);
692                                 if (class_constanttype (class, poolindex) == CONSTANT_Arraydescriptor) {
693                                         /* anewarray mit Array-Typ! */
694                                         constant_arraydescriptor *desc =
695                                           class_getconstant (class, poolindex, CONSTANT_Arraydescriptor);
696
697                                         v1 = stack_pop (TYPE_INT);
698                                         BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
699
700                                         v2 = var_create (TYPE_ADDRESS);
701                                         LOADCONST_A (desc, v2);
702
703                                         stack_makesaved ();
704                                         v = stack_push (TYPE_ADDRESS);
705                                         BUILTIN2 ((functionptr) builtin_newarray_array, v1,v2, v);
706                                         BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
707                                         }       
708                                 else {
709                                         classinfo *c = class_getconstant (class, poolindex, CONSTANT_Class);
710
711                                         v1 = stack_pop (TYPE_INT);
712                                         BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
713
714                                         v2 = var_create (TYPE_ADDRESS);
715                                         LOADCONST_A (c, v2);
716
717                                         stack_makesaved ();
718                                         v = stack_push (TYPE_ADDRESS);
719                                         BUILTIN2 ((functionptr) builtin_anewarray, v1,v2, v);
720                                         BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
721                                         }
722
723                                 break;
724
725
726                         case CMD_MULTIANEWARRAY:
727                                 { constant_arraydescriptor *desc =
728                                     class_getconstant (class, code_get_u2(p+1), CONSTANT_Arraydescriptor);
729                                   int i, n = code_get_u1 (p+3);
730                                   varid dims =      var_create (TYPE_ADDRESS);  /* array for dimensions */
731                                   varid dimsdim =   var_create (TYPE_INT);      /* groesse des arrays */
732
733                                 stack_makesaved ();
734                                 LOADCONST_I (n, dimsdim);
735                                 BUILTIN1 ((functionptr) builtin_newarray_int, dimsdim, dims);
736                                 BRA (CMD_IFNULL, dims,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
737
738                                 for (i=0; i<n; i++) {
739                                         varid dimn = stack_pop (TYPE_INT);
740                                         BRA (CMD_IFLT, dimn,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
741
742                                         LOADCONST_I ((n-i)-1, dimsdim);
743                                         OP3 (CMD_IASTORE, dims, dimsdim, dimn, NOVAR);
744                                         DROP (dimsdim);
745                                         DROP (dimn);
746                                         }
747
748                                 v = stack_push (TYPE_ADDRESS);
749
750                                 v1 = var_create (TYPE_ADDRESS);
751                                 LOADCONST_A (desc, v1);
752
753                                 BUILTIN2 ((functionptr) builtin_multianewarray, dims, v1, v);
754                                 BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
755
756                                 }
757                                 break;
758
759
760                         case CMD_ARRAYLENGTH:
761                                 v = stack_pop (TYPE_ADDRESS);
762                                 if (checknull) {
763 #ifdef STATISTICS
764                                         count_check_null++;
765 #endif
766                                         BRA (CMD_IFNULL, v,NOVAR, NOVAR,  EXCREATOR(proto_java_lang_NullPointerException) );
767                                         }
768                                 OP1 (opcode, v, stack_push (TYPE_INT) );
769                                 DROP (v);
770                                 break;
771
772                         case CMD_AALOAD:
773                                 type = TYPE_ADDRESS; goto do_aXload;
774                         case CMD_LALOAD:
775                                 type = TYPE_LONG; goto do_aXload;
776                         case CMD_FALOAD:
777                                 type = TYPE_FLOAT;  goto do_aXload;
778                         case CMD_DALOAD:
779                                 type = TYPE_DOUBLE; goto do_aXload;
780                         case CMD_IALOAD:
781                         case CMD_BALOAD:
782                         case CMD_CALOAD:
783                         case CMD_SALOAD:
784                                 type = TYPE_INT; goto do_aXload;
785                           do_aXload:
786                                 v2 = stack_pop (TYPE_INT);
787                                 v1 = stack_pop (TYPE_ADDRESS);
788                                 if (checknull) {
789 #ifdef STATISTICS
790                                         count_check_null++;
791 #endif
792                                         BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
793                                         }
794                                 if (checkbounds) {
795 #ifdef STATISTICS
796                                         count_check_bound++;
797 #endif
798                                         v = var_create (TYPE_INT);
799                                         OP1 (CMD_ARRAYLENGTH, v1, v);
800                                         BRA (CMD_IF_UCMPGE, v2,v, NOVAR, EXCREATOR(proto_java_lang_ArrayIndexOutOfBoundsException) );
801                                         DROP (v);
802                                         }
803                                 OP2 (opcode, v1,v2, stack_push (type) );
804                                 DROP (v1);
805                                 DROP (v2);
806                 break;
807
808                         case CMD_AASTORE:
809                                 type = TYPE_ADDRESS; goto do_aXstore;
810                         case CMD_LASTORE:
811                                 type = TYPE_LONG; goto do_aXstore;
812                         case CMD_FASTORE:
813                                 type = TYPE_FLOAT; goto do_aXstore;
814                         case CMD_DASTORE:
815                                 type = TYPE_DOUBLE; goto do_aXstore;
816                         case CMD_IASTORE:
817                         case CMD_BASTORE:
818                         case CMD_CASTORE:
819                         case CMD_SASTORE:
820                                 type = TYPE_INT; goto do_aXstore;
821                           do_aXstore:
822                                 v3 = stack_pop (type);
823                                 v2 = stack_pop (TYPE_INT);
824                                 v1 = stack_pop (TYPE_ADDRESS);
825                                 if (checknull) {
826 #ifdef STATISTICS
827                                         count_check_null++;
828 #endif
829                                         BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
830                                         }
831                                 if (checkbounds) {
832 #ifdef STATISTICS
833                                         count_check_bound++;
834 #endif
835                                         v = var_create (TYPE_INT);
836                                         OP1 (CMD_ARRAYLENGTH, v1, v);
837                                         BRA (CMD_IF_UCMPGE, v2,v, NOVAR, EXCREATOR(proto_java_lang_ArrayIndexOutOfBoundsException) );
838                                         DROP (v);
839                                         }
840
841                                 if (opcode!=CMD_AASTORE) {
842                                         OP3 (opcode, v1,v2,v3, NOVAR);
843                                         DROP (v1);
844                                         DROP (v2);
845                                         DROP (v3);
846                                 } else {
847                                         stack_makesaved ();
848
849                                         v = var_create (TYPE_INT);
850                                         BUILTIN3 ((functionptr) builtin_aastore, v1,v2,v3, v);
851                                         BRA (CMD_IFEQ, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ArrayStoreException) );
852                                         DROP (v);
853                                         }
854
855                                 break;
856
857
858
859                         /******************* Stack instructions **************************/
860
861                         case CMD_NOP:
862                                 break;
863
864                         case CMD_POP:
865                                 v1 = stack_popany (1);
866                                 DROP (v1);
867                                 break;
868
869                         case CMD_POP2:
870                                 { int varcount, i;
871                                   varid vararray[2];
872
873                                 varcount = stack_popmany (vararray, 2);
874                                 for (i=0; i<varcount; i++) DROP(vararray[i]);
875                                 }
876                                 break;
877
878                         case CMD_DUP:
879                                 v1 = stack_popany(1);
880                                 stack_repush (v1);
881                                 v = stack_push ( var_type (v1) );
882                                 MOVE (var_type(v1), v1,v);
883                                 break;
884
885                         case CMD_DUP2:
886                                 { int varcount, i;
887                                   varid vararray[2];
888
889                                 varcount = stack_popmany (vararray, 2);
890                                 stack_repushmany (varcount, vararray);
891                                 for (i=0; i<varcount; i++) {
892                                         v = stack_push ( var_type(vararray[varcount-1-i]) );
893                                         MOVE ( var_type(v), vararray[varcount-1-i], v);
894                                         }
895                                 }
896                                 break;
897
898                         case CMD_DUP_X1:
899                                 v1 = stack_popany(1);
900                                 v2 = stack_popany(1);
901
902                                 stack_repush (v1);
903                                 stack_repush (v2);
904                                 v = stack_push ( var_type (v1) );
905                                 MOVE (var_type(v1), v1,v);
906                                 break;
907
908                         case CMD_DUP2_X1:
909                                 { int varcount, i;
910                                   varid vararray[2];
911
912                                 varcount = stack_popmany (vararray, 2);
913                                 v3 = stack_popany (1);
914                                 stack_repushmany (varcount, vararray);
915                                 stack_repush (v3);
916                                 for (i=0; i<varcount; i++) {
917                                         v = stack_push ( var_type(vararray[varcount-1-i]) );
918                                         MOVE ( var_type(v), vararray[varcount-1-i], v);
919                                         }
920                                 }
921                                 break;
922
923                         case CMD_DUP_X2:
924                                 { int varcount;
925                                   varid vararray[2];
926
927                                 v1 = stack_popany(1);
928                                 varcount = stack_popmany (vararray, 2);
929                                 stack_repush (v1);
930                                 stack_repushmany (varcount, vararray);
931                                 MOVE (var_type(v1), v1, stack_push(var_type(v1)) );
932                                 }
933                                 break;
934
935                         case CMD_DUP2_X2:
936                                 { int varcount1, varcount2, i;
937                                   varid vararray1[2],vararray2[2];
938
939                                 varcount1 = stack_popmany (vararray1, 2);
940                                 varcount2 = stack_popmany (vararray2, 2);
941                                 stack_repushmany (varcount2, vararray2);
942                                 stack_repushmany (varcount1, vararray1);
943                                 for (i=0; i<varcount1; i++) {
944                                         v = stack_push ( var_type(vararray1[varcount1-1-i]) );
945                                         MOVE ( var_type(v), vararray1[varcount1-1-i], v);
946                                         }
947                                 }
948                                 break;
949
950             case CMD_SWAP:
951                                 v1 = stack_popany (1);
952                                 v2 = stack_popany (1);
953                                 stack_repush (v1);
954                                 stack_repush (v2);
955
956                             break;
957
958
959                         /*** Arithmetic & logical instructions ***/
960
961                         case CMD_IDIV:
962                         case CMD_IREM:
963                                 v2 = stack_pop (TYPE_INT);
964                                 v1 = stack_pop (TYPE_INT);
965                                 BRA (CMD_IFEQ, v2,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ArithmeticException) );
966
967                                 if (SUPPORT_DIVISION) {
968                                         OP2 (opcode, v1,v2, stack_push(TYPE_INT));
969                                         DROP (v1);
970                                         DROP (v2);
971                                         }
972                                 else {
973                                         stack_makesaved ();
974                                         BUILTIN2 (
975                                            (opcode == CMD_IDIV) ? 
976                                                 ((functionptr) builtin_idiv) 
977                                               : ((functionptr) builtin_irem) 
978                                           ,v1,v2, stack_push (TYPE_INT) );
979                                         }
980                                 break;
981
982                         case CMD_LDIV:
983                         case CMD_LREM:
984                                 v2 = stack_pop (TYPE_LONG);
985                                 v1 = stack_pop (TYPE_LONG);
986                                 BRA (CMD_IFEQL, v2,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ArithmeticException) );
987
988                                 if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV) {
989                                         OP2 (opcode, v1,v2, stack_push(TYPE_LONG));
990                                         DROP (v1);
991                                         DROP (v2);
992                                         }
993                                 else {
994                                         stack_makesaved ();
995                                         BUILTIN2 (
996                                            (opcode == CMD_LDIV) ? 
997                                                 ((functionptr) builtin_ldiv) 
998                                               : ((functionptr) builtin_lrem) 
999                                           ,v1,v2, stack_push (TYPE_LONG) );
1000                                         }
1001                                 break;
1002
1003
1004                         /*** Control transfer instructions ***/
1005
1006                         case CMD_IFEQ:
1007                         case CMD_IFLT:
1008                         case CMD_IFLE:
1009                         case CMD_IFNE:
1010                         case CMD_IFGT:
1011                         case CMD_IFGE:
1012                                 target = block_find (p + code_get_s2 (p+1) );
1013                                 v = stack_pop (TYPE_INT);
1014                                 block_reach (target);
1015                                 BRA_N_DROP (opcode, v,NOVAR, NOVAR, target);
1016                                 break;
1017
1018                         case CMD_IFNULL:
1019                         case CMD_IFNONNULL:
1020                                 target = block_find (p + code_get_s2 (p+1));
1021                                 v = stack_pop (TYPE_ADDRESS);
1022                                 block_reach (target);
1023                                 BRA_N_DROP (opcode, v,NOVAR, NOVAR, target);
1024                                 break;
1025
1026                         case CMD_IF_ICMPEQ:
1027                         case CMD_IF_ICMPNE:
1028                         case CMD_IF_ICMPLT:
1029                         case CMD_IF_ICMPGT:
1030                         case CMD_IF_ICMPLE:
1031                         case CMD_IF_ICMPGE:
1032                                 target = block_find (p + code_get_s2 (p+1) );
1033                                 v2 = stack_pop (TYPE_INT);
1034                                 v1 = stack_pop (TYPE_INT);
1035                                 block_reach (target);
1036                                 BRA_N_DROP (opcode, v1,v2, NOVAR, target );
1037                                 break;
1038
1039                         case CMD_IF_ACMPEQ:
1040                         case CMD_IF_ACMPNE:
1041                                 target = block_find (p + code_get_s2 (p+1) );
1042                                 v2 = stack_pop (TYPE_ADDRESS);
1043                                 v1 = stack_pop (TYPE_ADDRESS);
1044                                 block_reach (target);
1045                                 BRA_N_DROP (opcode, v1,v2, NOVAR, target);
1046                                 break;
1047
1048
1049                         case CMD_GOTO:
1050                                 target = block_find (p + code_get_s2 (p+1) );
1051                                 goto do_goto;
1052                         case CMD_GOTO_W:
1053                                 target = block_find (p + code_get_s4 (p+1) );
1054                           do_goto:
1055                                 block_reach (target);
1056                                 BRA (CMD_GOTO, NOVAR,NOVAR, NOVAR, target );
1057                                 goto cleanup;
1058
1059
1060                         case CMD_JSR:
1061                                 target = block_find (p + code_get_s2 (p+1) );
1062                                 goto do_jsr;
1063                         case CMD_JSR_W:
1064                                 target = block_find (p + code_get_s4 (p+1) );
1065                           do_jsr:
1066                                 {
1067                             subroutineinfo *sub;
1068
1069                                 ACTIVATE (stack_push (TYPE_ADDRESS) );
1070
1071                                 sub = target->subroutine;
1072                                 if (!sub) {
1073                                         sub = subroutine_new();
1074                                         target->subroutine = sub;
1075                                         }
1076
1077                                 subroutine_set (sub);
1078                                 block_reach (target);
1079                                 subroutine_set (b->subroutine);
1080
1081                                 BRA (CMD_JSR, NOVAR,NOVAR, stack_pop(TYPE_ADDRESS), target );
1082
1083                                 while (! stack_isempty() ) {
1084                                         v = stack_popany ( stack_topslots() );
1085                                         DROP (v);
1086                                         }
1087
1088                                 if (sub->returnfinished) {
1089                                         stackinfo *s = sub->returnstack;
1090                                         stack_restore (s);
1091                                         while (s) {
1092                                                 ACTIVATE (s->var);
1093                                                 s = s->prev;
1094                                                 }
1095                                         block_reach ( block_find(nextp) );
1096                                         }
1097                                 else {
1098                                         basicblock *n = block_find(nextp);
1099                                         n -> subroutine = b->subroutine;
1100
1101                                         chain_addlast (sub->callers, n );
1102                                         }
1103
1104                                 }
1105                                 goto cleanup;
1106
1107
1108                         case CMD_RET:
1109                                 if (!iswide) {
1110                                         v = local_get (code_get_u1 (p+1), TYPE_ADDRESS);
1111                                         }
1112                                 else {
1113                                         v = local_get (code_get_u2 (p+1), TYPE_ADDRESS);
1114                                         nextp = p+3;
1115                                         iswide = false;
1116                                         }
1117
1118                                 {
1119                                 subroutineinfo *sub;
1120                                 basicblock *bb;
1121
1122                                 sub = b->subroutine;
1123                                 if (!sub) panic ("RET outside of subroutine");
1124                                 if (sub->returnfinished) panic ("Multiple RET in a subroutine");
1125
1126                                 sub->returnfinished = true;
1127                                 sub->returnstack = stack_get() ;
1128
1129                                 while ( (bb = chain_first(sub->callers)) ) {
1130                                         chain_remove (sub->callers);
1131
1132                                         subroutine_set (bb->subroutine);
1133                                         block_reach ( bb );
1134                                         subroutine_set (sub);
1135                                         }
1136
1137                                 BRA (CMD_RET, v,NOVAR, NOVAR, NULL);
1138                                 }
1139                                 goto cleanup;
1140
1141
1142
1143                         /*************** Function Return **************/
1144
1145                         case CMD_IRETURN:
1146                                 addreturnhandling();
1147
1148                                 v = stack_pop (TYPE_INT);
1149                                 ve = var_create (TYPE_ADDRESS);
1150                                 LOADCONST_A (NULL, ve);
1151                                 BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
1152 #ifdef STATISTICS
1153         count_pcmd_return++;
1154 #endif
1155                                 goto cleanup;
1156
1157                         case CMD_LRETURN:
1158                                 addreturnhandling();
1159
1160                                 v = stack_pop (TYPE_LONG);
1161                                 var_proposereg (v, reg_parlistresult(TYPE_LONG) );
1162                                 ve = var_create (TYPE_ADDRESS);
1163                                 LOADCONST_A (NULL, ve);
1164                                 var_proposereg (ve, reg_parlistexception() );
1165                                 BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
1166 #ifdef STATISTICS
1167         count_pcmd_return++;
1168 #endif
1169                                 goto cleanup;
1170
1171                         case CMD_FRETURN:
1172                                 addreturnhandling();
1173
1174                                 v = stack_pop (TYPE_FLOAT);
1175                                 var_proposereg (v, reg_parlistresult(TYPE_FLOAT) );
1176                                 ve = var_create (TYPE_ADDRESS);
1177                                 LOADCONST_A (NULL, ve);
1178                                 var_proposereg (ve, reg_parlistexception() );
1179                                 BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
1180 #ifdef STATISTICS
1181         count_pcmd_return++;
1182 #endif
1183                                 goto cleanup;
1184
1185                         case CMD_DRETURN:
1186                                 addreturnhandling();
1187
1188                                 v = stack_pop (TYPE_DOUBLE);
1189                                 var_proposereg (v, reg_parlistresult(TYPE_DOUBLE) );
1190                                 ve = var_create (TYPE_ADDRESS);
1191                                 LOADCONST_A (NULL, ve);
1192                                 var_proposereg (ve, reg_parlistexception() );
1193                                 BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
1194 #ifdef STATISTICS
1195         count_pcmd_return++;
1196 #endif
1197                                 goto cleanup;
1198
1199                         case CMD_ARETURN:
1200                                 addreturnhandling();
1201
1202                                 v = stack_pop (TYPE_ADDRESS);
1203                                 var_proposereg (v, reg_parlistresult(TYPE_ADDRESS) );
1204                                 ve = var_create (TYPE_ADDRESS);
1205                                 LOADCONST_A (NULL, ve);
1206                                 var_proposereg (ve, reg_parlistexception() );
1207                                 BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
1208                                 goto cleanup;
1209 #ifdef STATISTICS
1210         count_pcmd_return++;
1211 #endif
1212
1213                         case CMD_RETURN:
1214                                 addreturnhandling();
1215
1216                                 ve = var_create (TYPE_ADDRESS);
1217                                 LOADCONST_A (NULL, ve);
1218                                 var_proposereg (ve, reg_parlistexception() );
1219                                 BRA_N_DROP (opcode, NOVAR,ve, NOVAR, NULL);
1220 #ifdef STATISTICS
1221         count_pcmd_return++;
1222 #endif
1223                                 goto cleanup;
1224
1225
1226                         case CMD_BREAKPOINT:
1227                                 break;
1228
1229
1230
1231                         /**************** Table Jumping *****************/
1232
1233                         case CMD_LOOKUPSWITCH:
1234                                 {       u4 p2 = ALIGN((p+1), 4);
1235                                         basicblock *defaulttarget;
1236                                         u4 num, i;
1237
1238                                         defaulttarget = block_find (p + code_get_s4 (p2) );
1239                                         num = code_get_s4 (p2+4);
1240
1241                                         v = stack_pop (TYPE_INT);
1242                                         for (i=0; i<num; i++) {
1243                                                 s4 value = code_get_s4 (p2 + 8 + 8*i);
1244                                                 target = block_find (p + code_get_s4 (p2 + 8 + 4 + 8*i) );
1245
1246                                                 v1 = var_create (TYPE_INT);
1247                                                 v2 = var_create (TYPE_INT);
1248                                                 MOVE (TYPE_INT, v, v1);
1249                                                 LOADCONST_I (value, v2);
1250                                                 block_reach (target);
1251                                                 BRA_N_DROP (CMD_IF_ICMPEQ, v1,v2, NOVAR, target );
1252                                                 }
1253
1254                                         DROP (v);
1255                                         block_reach (defaulttarget);
1256                                         BRA (CMD_GOTO, NOVAR,NOVAR, NOVAR, defaulttarget );
1257
1258                                         nextp = p2 + 8 + 8*num;
1259                                         goto cleanup;
1260                                 }
1261                                 break;
1262
1263                         case CMD_TABLESWITCH:
1264                                 {       u4 p2 = ALIGN((p+1), 4);
1265                                         basicblock *target;
1266                                         basicblock **targets;
1267                                         s4 low,high, i;
1268                                         
1269                                         low = code_get_s4 (p2+4);
1270                                         high = code_get_s4 (p2+8);
1271                                         if (high<low) panic ("Tablejump range invalid");
1272
1273                                         v = stack_pop (TYPE_INT);
1274
1275                                         target = block_find (p + code_get_s4 (p2) );
1276                                         block_reach(target);
1277
1278                                         v1 = var_create (TYPE_INT);
1279                                         LOADCONST_I (high, v1);
1280                                         BRA (CMD_IF_ICMPGT, v,v1, NOVAR, target);
1281                                         DROP (v1);
1282                                         
1283                                         if (low!=0) {
1284                                                 v1 = var_create (TYPE_INT);
1285                                                 v2 = var_create (TYPE_INT);
1286                                                 LOADCONST_I (low, v1);
1287                                                 OP2 (CMD_ISUB, v,v1, v2);
1288                                                 DROP (v1);
1289                                                 DROP (v);
1290                                                 v = v2;
1291                                                 } 
1292                                         BRA (CMD_IFLT, v,NOVAR, NOVAR, target);
1293                                                 
1294                                         targets = DMNEW (basicblock*, (high-low)+1);
1295                                         for (i=0; i < (high-low)+1; i++) {
1296                                                 target = block_find (p + code_get_s4 (p2 + 12 + 4*i) );
1297                                                 block_reach (target);
1298
1299                                                 targets[i] = target;
1300                                                 }
1301
1302                                         TABLEJUMP (v, (high-low)+1, targets);
1303                                         DROP (v);
1304
1305                                         nextp = p2 + 12 + 4 * ((high-low)+1);
1306                                         goto cleanup;
1307                                 }
1308                                 break;
1309
1310
1311                         /************ Manipulating Object Fields ********/
1312
1313                         case CMD_PUTSTATIC:
1314                         case CMD_GETSTATIC:
1315                         case CMD_PUTFIELD:
1316                         case CMD_GETFIELD:
1317
1318                                 poolindex = code_get_u2 (p+1);
1319                                 { constant_FMIref *fr;
1320                                   fieldinfo *fi;
1321
1322                                         fr = class_getconstant (class, poolindex, CONSTANT_Fieldref);
1323                                         fi = class_findfield (fr->class, fr->name, fr->descriptor);
1324
1325                                         switch (opcode) {
1326                                         case CMD_PUTSTATIC:
1327                                                 compiler_addinitclass (fr->class);
1328
1329                                                 v1 = var_create (TYPE_ADDRESS);
1330                                                 v = stack_pop (fi->type);
1331                                                 LOADCONST_A (&(fi->value), v1);
1332
1333                                                 MEM (CMD_PUTFIELD, fi->type, v1,v, NOVAR, 0);
1334                                                 DROP (v);
1335                                                 DROP (v1);
1336                                                 break;
1337
1338                                         case CMD_GETSTATIC:
1339                                                 compiler_addinitclass (fr->class);
1340
1341                                                 v1 = var_create (TYPE_ADDRESS);
1342                                                 v = stack_push (fi->type);
1343                                                 LOADCONST_A (&(fi->value), v1);
1344
1345                                                 MEM (CMD_GETFIELD, fi->type, v1,NOVAR, v, 0);
1346                                                 DROP (v1);
1347                                                 break;
1348
1349
1350                                         case CMD_PUTFIELD:
1351                                                 v = stack_pop (fi->type);
1352                                                 v1 = stack_pop (TYPE_ADDRESS);
1353                                                 if (checknull) {
1354 #ifdef STATISTICS
1355                                         count_check_null++;
1356 #endif
1357                                                         BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
1358                                                         }
1359                                                 MEM (CMD_PUTFIELD, fi->type, v1,v, NOVAR, fi->offset);
1360                                                 DROP (v);
1361                                                 DROP (v1);
1362                                                 break;
1363
1364                                         case CMD_GETFIELD:
1365                                                 v1 = stack_pop (TYPE_ADDRESS);
1366                                                 v = stack_push (fi->type);
1367                                                 if (checknull) {
1368 #ifdef STATISTICS
1369                                         count_check_null++;
1370 #endif
1371                                                         BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
1372                                                         }
1373                                                 MEM (CMD_GETFIELD, fi->type, v1,NOVAR, v, fi->offset);
1374                                                 DROP (v1);
1375                                                 break;
1376
1377
1378                                         }
1379                                 }
1380                                 break;
1381
1382
1383                         /*** Method invocation ***/
1384
1385                         case CMD_INVOKEVIRTUAL:
1386                         case CMD_INVOKESPECIAL:
1387                         case CMD_INVOKESTATIC:
1388                         case CMD_INVOKEINTERFACE:
1389                         
1390                                 count_calls ++;
1391                         
1392                                 { constant_FMIref *mr;
1393                                   methodinfo *mi;
1394                                   u4 i;
1395                                   s4 paramnum;
1396                                   u1 *paramtypes;
1397                                   s4 returntype;
1398                                   varid *params;
1399                                   bool stat = (opcode == CMD_INVOKESTATIC);
1400
1401                                 if (opcode==CMD_INVOKEINTERFACE) {
1402                                         poolindex = code_get_u2 (p+1);
1403                                         mr = class_getconstant (class, poolindex, CONSTANT_InterfaceMethodref);
1404                                         }
1405                                 else {
1406                                         poolindex = code_get_u2 (p+1);
1407                                         mr = class_getconstant (class, poolindex, CONSTANT_Methodref);
1408                                         }
1409
1410                                 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
1411
1412                                 if ( ((mi->flags & ACC_STATIC) != 0) != stat)
1413                                         panic ("Static/Nonstatic mismatch on method call");
1414
1415                                 descriptor2types (mi->descriptor, stat,
1416                           &paramnum, &paramtypes, &returntype);
1417                     mi->paramcount = paramnum;
1418
1419                                 params = DMNEW (varid, paramnum);
1420                                 for (i=0; i<paramnum; i++) {
1421                                         params[paramnum-i-1] = stack_pop (paramtypes[paramnum-i-1]);
1422                                         }
1423
1424                                 stack_makesaved();
1425
1426                                 if ((!stat) && checknull) {
1427 #ifdef STATISTICS
1428                                         count_check_null++;
1429 #endif
1430                                         BRA (CMD_IFNULL, params[0],NOVAR, NOVAR,  EXCREATOR(proto_java_lang_NullPointerException) );
1431                                         }
1432
1433                                 ve = var_create (TYPE_ADDRESS);
1434                                 if (returntype != TYPE_VOID) {
1435                                         v = stack_push (returntype);
1436                                         METHOD (opcode, mi, NULL, paramnum, params, v,  ve);
1437                                         }
1438                                 else {
1439                                         METHOD (opcode, mi, NULL, paramnum, params, NOVAR, ve);
1440                                         }
1441
1442                                 BRA (CMD_IFNONNULL, ve,NOVAR, NOVAR, EXFORWARDER(ve) );
1443                                 DROP (ve);
1444
1445                                 }
1446                                 break;
1447
1448
1449                         /********* Exception Handling *****************/
1450
1451                         case CMD_ATHROW:
1452                                 v = stack_pop (TYPE_ADDRESS);
1453                                 if (checknull) {
1454 #ifdef STATISTICS
1455                                         count_check_null++;
1456 #endif
1457                                         BRA (CMD_IFNULL, v,NOVAR, NOVAR,  EXCREATOR(proto_java_lang_NullPointerException) );
1458                                         }
1459                                 BRA (CMD_GOTO, NOVAR,NOVAR, NOVAR,  EXFORWARDER (v) );
1460                                 DROP (v);
1461                                 goto cleanup;
1462
1463
1464                         /***** Miscellaneous Object Operations ****/
1465
1466                         case CMD_NEW:
1467                                 poolindex = code_get_u2 (p+1);
1468                                 { classinfo *ci;
1469
1470                                 ci = class_getconstant (class, poolindex, CONSTANT_Class);
1471
1472                                 v1 = var_create (TYPE_ADDRESS);
1473                                 LOADCONST_A (ci, v1);
1474
1475                                 stack_makesaved ();
1476
1477                                 v = stack_push (TYPE_ADDRESS);
1478                                 BUILTIN1 ((functionptr) builtin_new, v1, v);
1479                                 BRA (CMD_IFNULL, v,NOVAR, NOVAR,  EXCREATOR(proto_java_lang_OutOfMemoryError) );
1480
1481                                 }
1482                                 break;
1483
1484
1485                         case CMD_CHECKCAST:
1486                                 poolindex = code_get_u2 (p+1);
1487
1488                                 if (class_constanttype (class, poolindex) == CONSTANT_Arraydescriptor) {
1489                                         /* cast-check auf Array-Typ! */
1490
1491                                         constant_arraydescriptor *desc =
1492                                           class_getconstant (class, poolindex, CONSTANT_Arraydescriptor);
1493
1494                                         v = stack_pop (TYPE_ADDRESS);
1495                                         stack_repush (v);
1496                                         v1 = var_create (TYPE_ADDRESS);
1497                                         MOVE (TYPE_ADDRESS, v,v1);
1498                                         v2 = var_create (TYPE_ADDRESS);
1499                                         LOADCONST_A (desc, v2);
1500
1501                                         stack_makesaved ();
1502                                         ve = var_create (TYPE_INT);
1503                                         BUILTIN2 ((functionptr) builtin_checkarraycast, v1,v2, ve);
1504
1505                                         BRA (CMD_IFEQ,ve,NOVAR, NOVAR,  EXCREATOR(proto_java_lang_ClassCastException) );
1506                                         DROP (ve);
1507                                         }
1508                                 else {
1509                                         /* cast-check auf Object-Typ */
1510
1511                                         classinfo *ci = class_getconstant (class, poolindex, CONSTANT_Class);
1512
1513                                         v = stack_pop (TYPE_ADDRESS);
1514                                         stack_repush (v);
1515                                         v1 = var_create (TYPE_ADDRESS);
1516                                         MOVE (TYPE_ADDRESS, v, v1);
1517                                         v2 = var_create (TYPE_ADDRESS);
1518                                         LOADCONST_A (ci, v2);
1519
1520                                         stack_makesaved ();
1521                                         ve = var_create (TYPE_INT);
1522                                         BUILTIN2 ((functionptr) builtin_checkcast, v1,v2, ve);
1523
1524                                         BRA (CMD_IFEQ,ve,NOVAR, NOVAR,  EXCREATOR(proto_java_lang_ClassCastException) );
1525                                         DROP (ve);
1526                                         }
1527
1528                                 break;
1529
1530
1531                         case CMD_INSTANCEOF:
1532                                 poolindex = code_get_u2 (p+1);
1533
1534                                 if (class_constanttype (class, poolindex) == CONSTANT_Arraydescriptor) {
1535                                         /* cast-check auf Array-Typ! */
1536
1537                                         constant_arraydescriptor *desc =
1538                                           class_getconstant (class, poolindex, CONSTANT_Arraydescriptor);
1539
1540                                         v = stack_pop (TYPE_ADDRESS);
1541                                         v1 = var_create (TYPE_ADDRESS);
1542                                         LOADCONST_A (desc, v1);
1543
1544                                         stack_makesaved ();
1545
1546                                         BUILTIN2 ((functionptr) builtin_arrayinstanceof, v,v1,
1547                                                       stack_push (TYPE_INT) );
1548                                         }
1549                                 else {
1550                                         classinfo *ci;  
1551                                         ci = class_getconstant (class, poolindex, CONSTANT_Class);
1552
1553                                         v = stack_pop (TYPE_ADDRESS);
1554                                         v1 = var_create (TYPE_ADDRESS);
1555                                         LOADCONST_A (ci, v1);
1556
1557                                         stack_makesaved ();
1558
1559                                         BUILTIN2 ((functionptr) builtin_instanceof, v,v1,
1560                                                       stack_push (TYPE_INT) );
1561                                         }
1562                                 break;
1563
1564
1565
1566
1567                         /*************** Monitors ************************/
1568
1569                         case CMD_MONITORENTER:
1570                                 if (checksync) {
1571                                         v = stack_pop (TYPE_ADDRESS);
1572                                         if (checknull) {
1573 #ifdef STATISTICS
1574                                                 count_check_null++;
1575 #endif
1576                                                 BRA (CMD_IFNULL, v, NOVAR, NOVAR,
1577                                                      EXCREATOR(proto_java_lang_NullPointerException));
1578                                                 }
1579                                         BUILTIN1 ((functionptr) builtin_monitorenter, v, NOVAR);
1580                                 } else {
1581                                         DROP (stack_pop (TYPE_ADDRESS));
1582                                         }                                       
1583                                 break;
1584
1585                         case CMD_MONITOREXIT:
1586                                 if (checksync) {
1587                                         BUILTIN1 ((functionptr) builtin_monitorexit, 
1588                                            stack_pop(TYPE_ADDRESS), NOVAR );
1589                                 } else {
1590                                         DROP (stack_pop (TYPE_ADDRESS));
1591                                         }                                       
1592                                 break;
1593
1594
1595
1596
1597                         /************** any other Basic-Operation **********/
1598
1599
1600                         default:
1601                                 {
1602                                 stdopdescriptor *s = stdopdescriptors[opcode];
1603                                 if (s) {
1604                                         v2 = NULL;
1605                                         if (s->type_s2 != TYPE_VOID) v2 = stack_pop(s->type_s2);
1606                                         v1 = stack_pop(s->type_s1);
1607
1608                                         if (s->supported) {
1609                                                 v = stack_push (s->type_d);
1610                                                 if (v2) {
1611                                                         OP2 (opcode, v1,v2, v);
1612                                                         DROP (v1);
1613                                                         DROP (v2);
1614                                                         }
1615                                                 else {
1616                                                         OP1 (opcode, v1, v);
1617                                                         DROP (v1);
1618                                                         }
1619                                                 }
1620                                         else {
1621                                                 stack_makesaved ();
1622                                                 v = stack_push (s->type_d);
1623                                                 if (v2) {
1624                                                         BUILTIN2 (s->builtin, v1,v2, v);
1625                                                         }
1626                                                 else {
1627                                                         BUILTIN1 (s->builtin, v1, v);
1628                                                         }
1629                                                 }
1630                                         }
1631                                                 
1632
1633                         /*************** invalid Opcode ***************/                
1634                                         
1635                                 else {
1636                                         sprintf (logtext, "Invalid opcode %d at position %ld",
1637                                                    opcode, (long int) p);
1638                                         error ();
1639                                         }
1640
1641                                 }
1642                                 
1643                                 break;
1644                                 
1645
1646                         } /* end switch */
1647
1648
1649                 p = nextp;
1650
1651                 if ( block_isany (p) ) {
1652                         block_reach ( block_find (p) );
1653                         goto cleanup;
1654                         }
1655
1656                 } /* end for */
1657
1658
1659 cleanup:
1660         pcmd_untieall();
1661 }
1662