* src/vm/resolve.c (resolve_method_verifier_checks)
[cacao.git] / src / vm / jit / intrp / codegen.c
1 /* src/vm/jit/intrp/codegen.c - code generator for Interpreter
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Christian Thalinger
28             Anton Ertl
29                         
30    Changes: Edwin Steiner
31
32    $Id: codegen.c 4863 2006-04-30 16:17:44Z edwin $
33
34 */
35
36
37 #include "config.h"
38
39 #include <assert.h>
40 #include <stdio.h>
41
42 #if defined(WITH_FFI)
43 # include <ffi.h>
44 #elif defined(WITH_FFCALL)
45 # include <avcall.h>
46 #else
47 # error neither WITH_FFI nor WITH_FFCALL defined
48 #endif
49
50 #include "vm/types.h"
51
52 #include "arch.h"
53
54 #include "vm/jit/intrp/codegen.h"
55 #include "vm/jit/intrp/intrp.h"
56
57 #include "native/native.h"
58 #include "vm/builtin.h"
59 #include "vm/class.h"
60 #include "vm/exceptions.h"
61 #include "vm/global.h"
62 #include "vm/options.h"
63 #include "vm/stringlocal.h"
64 #include "vm/vm.h"
65 #include "vm/jit/asmpart.h"
66 #include "vm/jit/codegen-common.h"
67 #include "vm/jit/dseg.h"
68 #include "vm/jit/jit.h"
69 #include "vm/jit/parse.h"
70 #include "vm/jit/patcher.h"
71
72
73 #define gen_branch(_inst) { \
74   gen_##_inst(cd, 0); \
75   codegen_addreference(cd, (basicblock *) (iptr->target)); \
76 }
77
78 #define index2offset(_i) (-(_i) * SIZEOF_VOID_P)
79
80 /* functions used by cacao-gen.i */
81
82 void genarg_v(codegendata *cd1, Cell v)
83 {
84         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
85         *((Cell *) *mcodepp) = v;
86         (*mcodepp)++;
87 }
88
89 void genarg_i(codegendata *cd1, s4 i)
90 {
91         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
92         *((Cell *) *mcodepp) = i;
93         (*mcodepp)++;
94 }
95
96 void genarg_b(codegendata *cd1, s4 i)
97 {
98   genarg_i(cd1, i);
99 }
100
101 void genarg_f(codegendata *cd1, float f)
102 {
103         s4 fi;
104
105         vm_f2Cell(f,fi);
106         genarg_i(cd1, fi);
107 }
108
109 void genarg_l(codegendata *cd1, s8 l)
110 {
111         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
112         vm_l2twoCell(l, ((Cell *) *mcodepp)[1], ((Cell *) *mcodepp)[0]);
113         (*mcodepp) +=2;
114 }
115
116 void genarg_aRef(codegendata *cd1, java_objectheader *a)
117 {
118         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
119         *((java_objectheader **) *mcodepp) = a;
120         (*mcodepp)++;
121 }
122
123 void genarg_aArray(codegendata *cd1, java_arrayheader *a)
124 {
125         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
126         *((java_arrayheader **) *mcodepp) = a;
127         (*mcodepp)++;
128 }
129
130 void genarg_aaTarget(codegendata *cd1, Inst **a)
131 {
132         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
133         *((Inst ***) *mcodepp) = a;
134         (*mcodepp)++;
135 }
136
137 void genarg_aClass(codegendata *cd1, classinfo *a)
138 {
139         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
140         *((classinfo **) *mcodepp) = a;
141         (*mcodepp)++;
142 }
143
144 void genarg_acr(codegendata *cd1, constant_classref *a)
145 {
146         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
147         *((constant_classref **) *mcodepp) = a;
148         (*mcodepp)++;
149 }
150
151 void genarg_addr(codegendata *cd1, u1 *a)
152 {
153         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
154         *((u1 **) *mcodepp) = a;
155         (*mcodepp)++;
156 }
157
158 void genarg_af(codegendata *cd1, functionptr a)
159 {
160         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
161         *((functionptr *) *mcodepp) = a;
162         (*mcodepp)++;
163 }
164
165 void genarg_afi(codegendata *cd1, fieldinfo *a)
166 {
167         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
168         *((fieldinfo **) *mcodepp) = a;
169         (*mcodepp)++;
170 }
171
172 void genarg_am(codegendata *cd1, methodinfo *a)
173 {
174         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
175         *((methodinfo **) *mcodepp) = a;
176         (*mcodepp)++;
177 }
178
179 void genarg_acell(codegendata *cd1, Cell *a)
180 {
181         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
182         *((Cell **) *mcodepp) = a;
183         (*mcodepp)++;
184 }
185
186 void genarg_ainst(codegendata *cd1, Inst *a)
187 {
188         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
189         *((Inst **) *mcodepp) = a;
190         (*mcodepp)++;
191 }
192
193 void genarg_auf(codegendata *cd1, unresolved_field *a)
194 {
195         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
196         *((unresolved_field **) *mcodepp) = a;
197         (*mcodepp)++;
198 }
199
200 void genarg_aum(codegendata *cd1, unresolved_method *a)
201 {
202         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
203         *((unresolved_method **) *mcodepp) = a;
204         (*mcodepp)++;
205 }
206
207 void genarg_avftbl(codegendata *cd1, vftbl_t *a)
208 {
209         Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
210         *((vftbl_t **) *mcodepp) = a;
211         (*mcodepp)++;
212 }
213
214
215 /* include the interpreter generation functions *******************************/
216
217 #include "vm/jit/intrp/java-gen.i"
218
219
220 typedef void (*genfunctionptr) (codegendata *);
221
222 typedef struct builtin_gen builtin_gen;
223
224 struct builtin_gen {
225         functionptr builtin;
226         genfunctionptr gen;
227 };
228
229 struct builtin_gen builtin_gen_table[] = {
230     {BUILTIN_new,                     gen_NEW,             }, 
231     {BUILTIN_newarray,                gen_NEWARRAY,        },
232     {BUILTIN_newarray_boolean,        gen_NEWARRAY_BOOLEAN,},
233     {BUILTIN_newarray_byte,           gen_NEWARRAY_BYTE,   },
234     {BUILTIN_newarray_char,           gen_NEWARRAY_CHAR,   },
235     {BUILTIN_newarray_short,          gen_NEWARRAY_SHORT,  },    
236     {BUILTIN_newarray_int,            gen_NEWARRAY_INT,    },
237     {BUILTIN_newarray_long,           gen_NEWARRAY_LONG,   },
238     {BUILTIN_newarray_float,          gen_NEWARRAY_FLOAT,  },    
239     {BUILTIN_newarray_double,         gen_NEWARRAY_DOUBLE, },
240     {BUILTIN_arrayinstanceof,         gen_ARRAYINSTANCEOF, },
241
242 #if defined(USE_THREADS)
243     {BUILTIN_monitorenter,            gen_MONITORENTER,    },
244     {BUILTIN_monitorexit,             gen_MONITOREXIT,     },
245 #endif
246
247 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
248     {BUILTIN_f2l,                     gen_F2L,             },
249 #endif
250
251 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
252     {BUILTIN_d2l,                                         gen_D2L,                         },
253 #endif
254
255 #if !(SUPPORT_FLOAT && SUPPORT_F2I)
256     {BUILTIN_f2i,                                         gen_F2I,                         },
257 #endif
258
259 #if !(SUPPORT_DOUBLE && SUPPORT_D2I)
260     {BUILTIN_d2i,                                         gen_D2I,                         },
261 #endif
262
263 #if !SUPPORT_DIVISION
264     {BUILTIN_idiv,                                        gen_IDIV,                        },
265     {BUILTIN_irem,                                        gen_IREM,                        },
266 #endif
267
268 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
269     {BUILTIN_ldiv,                                        gen_LDIV,                        },
270     {BUILTIN_lrem,                                        gen_LREM,                        },
271 #endif
272
273     {BUILTIN_frem,                                        gen_FREM,                        },
274     {BUILTIN_drem,                                        gen_DREM,            },
275 };
276
277
278 /* codegen *********************************************************************
279
280    Generates machine code.
281
282 *******************************************************************************/
283
284 bool intrp_codegen(jitdata *jd)
285 {
286         methodinfo         *m;
287         codegendata        *cd;
288         registerdata       *rd;
289         s4                  i, len, s1, s2, d;
290         stackptr            src;
291         basicblock         *bptr;
292         instruction        *iptr;
293         exceptiontable     *ex;
294         u2                  currentline;
295         methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
296         unresolved_method  *um;
297         builtintable_entry *bte;
298         methoddesc         *md;
299
300         /* get required compiler data */
301
302         m  = jd->m;
303         cd = jd->cd;
304         rd = jd->rd;
305
306         /* prevent compiler warnings */
307
308         d = 0;
309         currentline = 0;
310         lm = NULL;
311         bte = NULL;
312
313         /* create method header */
314
315         (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
316         (void) dseg_adds4(cd, m->maxlocals * SIZEOF_VOID_P);    /* FrameSize      */
317
318 #if defined(USE_THREADS)
319         if (checksync && (m->flags & ACC_SYNCHRONIZED))
320                 (void) dseg_adds4(cd, 1);                           /* IsSync         */
321         else
322 #endif
323                 (void) dseg_adds4(cd, 0);                           /* IsSync         */
324                                                
325         (void) dseg_adds4(cd, 0);                               /* IsLeaf         */
326         (void) dseg_adds4(cd, 0);                               /* IntSave        */
327         (void) dseg_adds4(cd, 0);                               /* FltSave        */
328
329         dseg_addlinenumbertablesize(cd);
330
331         (void) dseg_adds4(cd, cd->exceptiontablelength);        /* ExTableSize    */
332
333         /* create exception table */
334
335         for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
336                 dseg_addtarget(cd, ex->start);
337                 dseg_addtarget(cd, ex->end);
338                 dseg_addtarget(cd, ex->handler);
339                 (void) dseg_addaddress(cd, ex->catchtype.cls);
340         }
341
342 #if 0   
343         /* initialize mcode variables */
344         
345         cd->mcodeptr = cd->mcodebase;
346         cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
347 #endif
348
349         gen_BBSTART;
350
351 #if defined(USE_THREADS)
352         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
353                 if (m->flags & ACC_STATIC)
354                         gen_ACONST(cd, (java_objectheader *) m->class);
355                 else
356                         gen_ALOAD(cd, 0);
357                 
358                 gen_MONITORENTER(cd);
359         }                       
360 #endif
361
362         if (opt_verbosecall)
363                 gen_TRACECALL(cd, m);
364
365         gen_BBEND;
366
367         /* walk through all basic blocks */
368
369         for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
370
371                 bptr->mpc = (s4) ((u1 *) cd->mcodeptr - cd->mcodebase);
372
373                 if (bptr->flags >= BBREACHED) {
374
375                 /* walk through all instructions */
376                 
377                 src = bptr->instack;
378                 len = bptr->icount;
379
380                 gen_BBSTART;
381
382                 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
383                         if (iptr->line != currentline) {
384                                 dseg_addlinenumber(cd, iptr->line);
385                                 currentline = iptr->line;
386                         }
387
388                 MCODECHECK(64);       /* an instruction usually needs < 64 words      */
389
390                 switch (iptr->opc) {
391
392                 case ICMD_INLINE_START:
393                 case ICMD_INLINE_END:
394                         break;
395
396                 case ICMD_NOP:        /* ...  ==> ...                                 */
397                         break;
398
399                 case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
400
401                         gen_CHECKNULL(cd);
402                         break;
403
404                 /* constant operations ************************************************/
405
406                 case ICMD_ICONST:     /* ...  ==> ..., constant                       */
407                                       /* op1 = 0, val.i = constant                    */
408
409                         gen_ICONST(cd, iptr->val.i);
410                         break;
411
412                 case ICMD_LCONST:     /* ...  ==> ..., constant                       */
413                                       /* op1 = 0, val.l = constant                    */
414
415                         gen_LCONST(cd, iptr->val.l);
416                         break;
417
418                 case ICMD_FCONST:     /* ...  ==> ..., constant                       */
419                                       /* op1 = 0, val.f = constant                    */
420                         {
421                                 ptrint fi;
422
423                                 vm_f2Cell(iptr->val.f, fi);
424                                 gen_ICONST(cd, fi);
425                         }
426                         break;
427                         
428                 case ICMD_DCONST:     /* ...  ==> ..., constant                       */
429                                       /* op1 = 0, val.d = constant                    */
430
431                         gen_LCONST(cd, *(s8 *)&(iptr->val.d));
432                         break;
433
434                 case ICMD_ACONST:     /* ...  ==> ..., constant                       */
435                                       /* op1 = 0, val.a = constant                    */
436
437                         if (INSTRUCTION_IS_UNRESOLVED(iptr))
438                                 gen_PATCHER_ACONST(cd, NULL,
439                                                                    ICMD_ACONST_UNRESOLVED_CLASSREF(iptr));
440                         else
441                                 gen_ACONST(cd, iptr->val.a);
442                         break;
443
444
445                 /* load/store operations **********************************************/
446
447                 case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
448                                       /* op1 = local variable                         */
449
450                         gen_ILOAD(cd, index2offset(iptr->op1));
451                         break;
452
453                 case ICMD_LLOAD:      /* ...  ==> ..., content of local variable      */
454                                       /* op1 = local variable                         */
455
456                         gen_LLOAD(cd, index2offset(iptr->op1));
457                         break;
458
459                 case ICMD_ALOAD:      /* ...  ==> ..., content of local variable      */
460                                       /* op1 = local variable                         */
461
462                         gen_ALOAD(cd, index2offset(iptr->op1));
463                         break;
464
465                 case ICMD_FLOAD:      /* ...  ==> ..., content of local variable      */
466                                       /* op1 = local variable                         */
467
468                         gen_ILOAD(cd, index2offset(iptr->op1));
469                         break;
470
471                 case ICMD_DLOAD:      /* ...  ==> ..., content of local variable      */
472                                       /* op1 = local variable                         */
473
474                         gen_LLOAD(cd, index2offset(iptr->op1));
475                         break;
476
477
478                 case ICMD_ISTORE:     /* ..., value  ==> ...                          */
479                                       /* op1 = local variable                         */
480
481                         gen_ISTORE(cd, index2offset(iptr->op1));
482                         break;
483
484                 case ICMD_LSTORE:     /* ..., value  ==> ...                          */
485                                       /* op1 = local variable                         */
486
487                         gen_LSTORE(cd, index2offset(iptr->op1));
488                         break;
489
490                 case ICMD_ASTORE:     /* ..., value  ==> ...                          */
491                                       /* op1 = local variable                         */
492
493                         gen_ASTORE(cd, index2offset(iptr->op1));
494                         break;
495
496
497                 case ICMD_FSTORE:     /* ..., value  ==> ...                          */
498                                       /* op1 = local variable                         */
499
500                         gen_ISTORE(cd, index2offset(iptr->op1));
501                         break;
502
503                 case ICMD_DSTORE:     /* ..., value  ==> ...                          */
504                                       /* op1 = local variable                         */
505
506                         gen_LSTORE(cd, index2offset(iptr->op1));
507                         break;
508
509
510                 /* pop/dup/swap operations ********************************************/
511
512                 /* attention: double and longs are only one entry in CACAO ICMDs      */
513
514                 /* stack.c changes stack manipulation operations to treat
515                    longs/doubles as occupying a single slot.  Here we are
516                    undoing that (and only those things that stack.c did). */
517
518                 case ICMD_POP:        /* ..., value  ==> ...                          */
519
520                         if (IS_2_WORD_TYPE(src->type))
521                                 gen_POP2(cd);
522                         else
523                                 gen_POP(cd);
524                         break;
525
526                 case ICMD_POP2:       /* ..., value, value  ==> ...                   */
527
528                         gen_POP2(cd);
529                         break;
530
531                 case ICMD_DUP:        /* ..., a ==> ..., a, a                         */
532
533                         if (IS_2_WORD_TYPE(src->type))
534                                 gen_DUP2(cd);
535                         else
536                                 gen_DUP(cd);
537                         break;
538
539                 case ICMD_DUP_X1:     /* ..., a, b ==> ..., b, a, b                   */
540
541                         if (IS_2_WORD_TYPE(src->type)) {
542                                 if (IS_2_WORD_TYPE(src->prev->type)) {
543                                         gen_DUP2_X2(cd);
544                                 } else {
545                                         gen_DUP2_X1(cd);
546                                 }
547                         } else {
548                                 if (IS_2_WORD_TYPE(src->prev->type)) {
549                                         gen_DUP_X2(cd);
550                                 } else {
551                                         gen_DUP_X1(cd);
552                                 }
553                         }
554                         break;
555
556                 case ICMD_DUP_X2:     /* ..., a, b, c ==> ..., c, a, b, c             */
557
558                         if (IS_2_WORD_TYPE(src->type)) {
559                                 gen_DUP2_X2(cd);
560                         } else
561                                 gen_DUP_X2(cd);
562                         break;
563
564                 case ICMD_DUP2:       /* ..., a, b ==> ..., a, b, a, b                */
565
566                         gen_DUP2(cd);
567                         break;
568
569                 case ICMD_DUP2_X1:    /* ..., a, b, c ==> ..., b, c, a, b, c          */
570
571                         if (IS_2_WORD_TYPE(src->prev->prev->type))
572                                 gen_DUP2_X2(cd);
573                         else
574                                 gen_DUP2_X1(cd);
575                         break;
576
577                 case ICMD_DUP2_X2:    /* ..., a, b, c, d ==> ..., c, d, a, b, c, d    */
578
579                         gen_DUP2_X2(cd);
580                         break;
581
582                 case ICMD_SWAP:       /* ..., a, b ==> ..., b, a                      */
583
584                         gen_SWAP(cd);
585                         break;
586
587
588                 /* integer operations *************************************************/
589
590                 case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
591
592                         gen_INEG(cd);
593                         break;
594
595                 case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
596
597                         gen_LNEG(cd);
598                         break;
599
600                 case ICMD_I2L:        /* ..., value  ==> ..., value                   */
601
602                         gen_I2L(cd);
603                         break;
604
605                 case ICMD_L2I:        /* ..., value  ==> ..., value                   */
606
607                         gen_L2I(cd);
608                         break;
609
610                 case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
611
612                         gen_INT2BYTE(cd);
613                         break;
614
615                 case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
616
617                         gen_INT2CHAR(cd);
618                         break;
619
620                 case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
621
622                         gen_INT2SHORT(cd);
623                         break;
624
625
626                 case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
627
628                         gen_IADD(cd);
629                         break;
630
631                 case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant        */
632                                       /* val.i = constant                             */
633
634                         gen_ICONST(cd, iptr->val.i);
635                         gen_IADD(cd);
636                         break;
637
638                 case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
639
640                         gen_LADD(cd);
641                         break;
642
643                 case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
644                                       /* val.l = constant                             */
645
646                         gen_LCONST(cd, iptr->val.l);
647                         gen_LADD(cd);
648                         break;
649
650                 case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
651
652                         gen_ISUB(cd);
653                         break;
654
655                 case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
656                                       /* val.i = constant                             */
657
658                         gen_ICONST(cd, iptr->val.i);
659                         gen_ISUB(cd);
660                         break;
661
662                 case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
663
664                         gen_LSUB(cd);
665                         break;
666
667                 case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
668                                       /* val.l = constant                             */
669
670                         gen_LCONST(cd, iptr->val.l);
671                         gen_LSUB(cd);
672                         break;
673
674                 case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
675
676                         gen_IMUL(cd);
677                         break;
678
679                 case ICMD_IMULCONST:  /* ..., val1, val2  ==> ..., val1 * val2        */
680
681                         gen_ICONST(cd, iptr->val.i);
682                         gen_IMUL(cd);
683                         break;
684
685                 case ICMD_LMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
686
687                         gen_LMUL(cd);
688                         break;
689
690                 case ICMD_LMULCONST:  /* ..., val1, val2  ==> ..., val1 * val2        */
691
692                         gen_LCONST(cd, iptr->val.l);
693                         gen_LMUL(cd);
694                         break;
695
696                 case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
697
698                         gen_IDIV(cd);
699                         break;
700
701                 case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
702
703                         gen_IREM(cd);
704                         break;
705
706                 case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
707
708                         gen_LDIV(cd);
709                         break;
710
711                 case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
712
713                         gen_LREM(cd);
714                         break;
715
716                 case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value << constant       */
717                                       /* val.i = constant                             */
718                                       
719                         gen_IDIVPOW2(cd, iptr->val.i);
720                         break;
721
722                 case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
723                                       /* val.i = constant                             */
724
725                         gen_IREMPOW2(cd, iptr->val.i);
726                         break;
727
728                 case ICMD_LDIVPOW2:   /* ..., value  ==> ..., value << constant       */
729                                       /* val.i = constant                             */
730                                       
731                         gen_LDIVPOW2(cd, iptr->val.i);
732                         break;
733
734                 case ICMD_LREMPOW2:   /* ..., value  ==> ..., value % constant        */
735                                       /* val.l = constant                             */
736
737                         gen_LREMPOW2(cd, iptr->val.i);
738                         break;
739
740                 case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
741
742                         gen_ISHL(cd);
743                         break;
744
745                 case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
746                                       /* val.i = constant                             */
747
748                         gen_ICONST(cd, iptr->val.i);
749                         gen_ISHL(cd);
750                         break;
751
752                 case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
753
754                         gen_ISHR(cd);
755                         break;
756
757                 case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
758                                       /* val.i = constant                             */
759
760                         gen_ICONST(cd, iptr->val.i);
761                         gen_ISHR(cd);
762                         break;
763
764                 case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
765
766                         gen_IUSHR(cd);
767                         break;
768
769                 case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
770                                       /* val.i = constant                             */
771
772                         gen_ICONST(cd, iptr->val.i);
773                         gen_IUSHR(cd);
774                         break;
775
776                 case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
777
778                         gen_LSHL(cd);
779                         break;
780
781                 case ICMD_LSHLCONST:  /* ..., value  ==> ..., value << constant       */
782                                       /* val.i = constant                             */
783
784                         gen_ICONST(cd, iptr->val.i);
785                         gen_LSHL(cd);
786                         break;
787
788                 case ICMD_LSHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
789
790                         gen_LSHR(cd);
791                         break;
792
793                 case ICMD_LSHRCONST:  /* ..., value  ==> ..., value >> constant       */
794                                       /* val.i = constant                             */
795
796                         gen_ICONST(cd, iptr->val.i);
797                         gen_LSHR(cd);
798                         break;
799
800                 case ICMD_LUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
801
802                         gen_LUSHR(cd);
803                         break;
804
805                 case ICMD_LUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
806                                       /* val.i = constant                             */
807
808                         gen_ICONST(cd, iptr->val.i);
809                         gen_LUSHR(cd);
810                         break;
811
812                 case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
813
814                         gen_IAND(cd);
815                         break;
816
817                 case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
818                                       /* val.i = constant                             */
819
820                         gen_ICONST(cd, iptr->val.i);
821                         gen_IAND(cd);
822                         break;
823
824                 case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
825
826                         gen_LAND(cd);
827                         break;
828
829                 case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
830                                       /* val.l = constant                             */
831
832                         gen_LCONST(cd, iptr->val.l);
833                         gen_LAND(cd);
834                         break;
835
836                 case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
837
838                         gen_IOR(cd);
839                         break;
840
841                 case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
842                                       /* val.i = constant                             */
843
844                         gen_ICONST(cd, iptr->val.i);
845                         gen_IOR(cd);
846                         break;
847
848                 case ICMD_LOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
849
850                         gen_LOR(cd);
851                         break;
852
853                 case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
854                                       /* val.l = constant                             */
855
856                         gen_LCONST(cd, iptr->val.l);
857                         gen_LOR(cd);
858                         break;
859
860                 case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
861
862                         gen_IXOR(cd);
863                         break;
864
865                 case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
866                                       /* val.i = constant                             */
867
868                         gen_ICONST(cd, iptr->val.i);
869                         gen_IXOR(cd);
870                         break;
871
872                 case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
873
874                         gen_LXOR(cd);
875                         break;
876
877                 case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
878                                       /* val.l = constant                             */
879
880                         gen_LCONST(cd, iptr->val.l);
881                         gen_LXOR(cd);
882                         break;
883
884
885                 case ICMD_LCMP:       /* ..., val1, val2  ==> ..., val1 cmp val2      */
886
887                         gen_LCMP(cd);
888                         break;
889
890
891                 case ICMD_IINC:       /* ..., value  ==> ..., value + constant        */
892                                       /* op1 = variable, val.i = constant             */
893
894                         gen_IINC(cd, index2offset(iptr->op1), iptr->val.i);
895                         break;
896
897
898                 /* floating operations ************************************************/
899
900                 case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
901
902                         gen_FNEG(cd);
903                         break;
904
905                 case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
906
907                         gen_DNEG(cd);
908                         break;
909
910                 case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
911
912                         gen_FADD(cd);
913                         break;
914
915                 case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
916
917                         gen_DADD(cd);
918                         break;
919
920                 case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
921
922                         gen_FSUB(cd);
923                         break;
924
925                 case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
926
927                         gen_DSUB(cd);
928                         break;
929
930                 case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
931
932                         gen_FMUL(cd);
933                         break;
934
935                 case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 *** val2      */
936
937                         gen_DMUL(cd);
938                         break;
939
940                 case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
941
942                         gen_FDIV(cd);
943                         break;
944
945                 case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
946
947                         gen_DDIV(cd);
948                         break;
949                 
950                 case ICMD_FREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
951
952                         gen_FREM(cd);
953                         break;
954
955                 case ICMD_DREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
956
957                         gen_DREM(cd);
958                         break;
959                 
960                 case ICMD_I2F:       /* ..., value  ==> ..., (float) value            */
961
962                         gen_I2F(cd);
963                         break;
964
965                 case ICMD_L2F:       /* ..., value  ==> ..., (float) value            */
966
967                         gen_L2F(cd);
968                         break;
969
970                 case ICMD_I2D:       /* ..., value  ==> ..., (double) value           */
971
972                         gen_I2D(cd);
973                         break;
974                         
975                 case ICMD_L2D:       /* ..., value  ==> ..., (double) value           */
976
977                         gen_L2D(cd);
978                         break;
979                         
980                 case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
981
982                         gen_F2I(cd);
983                         break;
984                 
985                 case ICMD_D2I:       /* ..., value  ==> ..., (int) value              */
986
987                         gen_D2I(cd);
988                         break;
989                 
990                 case ICMD_F2L:       /* ..., value  ==> ..., (long) value             */
991
992                         gen_F2L(cd);
993                         break;
994
995                 case ICMD_D2L:       /* ..., value  ==> ..., (long) value             */
996
997                         gen_D2L(cd);
998                         break;
999
1000                 case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
1001
1002                         gen_F2D(cd);
1003                         break;
1004                                         
1005                 case ICMD_D2F:       /* ..., value  ==> ..., (float) value            */
1006
1007                         gen_D2F(cd);
1008                         break;
1009                 
1010                 case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1011
1012                         gen_FCMPL(cd);
1013                         break;
1014                         
1015                 case ICMD_DCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1016
1017                         gen_DCMPL(cd);
1018                         break;
1019                         
1020                 case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1021
1022                         gen_FCMPG(cd);
1023                         break;
1024
1025                 case ICMD_DCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1026
1027                         gen_DCMPG(cd);
1028                         break;
1029
1030
1031                 /* memory operations **************************************************/
1032
1033                 case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
1034
1035                         gen_ARRAYLENGTH(cd);
1036                         break;
1037
1038                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
1039
1040                         gen_BALOAD(cd);
1041                         break;
1042
1043                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
1044
1045                         gen_CALOAD(cd);
1046                         break;                  
1047
1048                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
1049
1050                         gen_SALOAD(cd);
1051                         break;
1052
1053                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
1054
1055                         gen_IALOAD(cd);
1056                         break;
1057
1058                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
1059
1060                         gen_FALOAD(cd);
1061                         break;
1062
1063                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
1064                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
1065
1066                         gen_LALOAD(cd);
1067                         break;
1068
1069                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
1070
1071                         gen_AALOAD(cd);
1072                         break;
1073
1074
1075                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
1076
1077                         gen_BASTORE(cd);
1078                         break;
1079
1080                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
1081                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
1082
1083                         gen_CASTORE(cd);
1084                         break;
1085
1086                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
1087
1088                         gen_IASTORE(cd);
1089                         break;
1090
1091                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
1092
1093                         gen_FASTORE(cd);
1094                         break;
1095
1096                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
1097                 case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
1098
1099                         gen_LASTORE(cd);
1100                         break;
1101
1102                 case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
1103
1104                         gen_AASTORE(cd);
1105                         break;
1106
1107
1108                 case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
1109                                       /* op1 = type, val.a = field address            */
1110
1111                         {
1112                         fieldinfo *fi = NULL;
1113                         unresolved_field *uf = NULL;
1114
1115                         if (INSTRUCTION_IS_UNRESOLVED(iptr))
1116                                 uf = INSTRUCTION_UNRESOLVED_FIELD(iptr);
1117                         else
1118                                 fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
1119
1120                         switch (iptr->op1) {
1121                         case TYPE_INT:
1122                                 if (fi == NULL) {
1123                                         gen_PATCHER_GETSTATIC_INT(cd, 0, uf);
1124                                 } else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1125                                         gen_PATCHER_GETSTATIC_CLINIT_INT(cd, 0, fi);
1126                                 } else {
1127                                         gen_GETSTATIC_INT(cd, (u1 *)&(fi->value.i), fi);
1128                                 }
1129                                 break;
1130                         case TYPE_FLT:
1131                                 if (fi == NULL) {
1132                                         gen_PATCHER_GETSTATIC_FLOAT(cd, 0, uf);
1133                                 } else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1134                                         gen_PATCHER_GETSTATIC_CLINIT_FLOAT(cd, 0, fi);
1135                                 } else {
1136                                         gen_GETSTATIC_FLOAT(cd, (u1 *)&(fi->value.i), fi);
1137                                 }
1138                                 break;
1139                         case TYPE_LNG:
1140                         case TYPE_DBL:
1141                                 if (fi == NULL) {
1142                                         gen_PATCHER_GETSTATIC_LONG(cd, 0, uf);
1143                                 } else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1144                                         gen_PATCHER_GETSTATIC_CLINIT_LONG(cd, 0, fi);
1145                                 } else {
1146                                         gen_GETSTATIC_LONG(cd, (u1 *)&(fi->value.l), fi);
1147                                 }
1148                                 break;
1149                         case TYPE_ADR:
1150                                 if (fi == NULL) {
1151                                         gen_PATCHER_GETSTATIC_CELL(cd, 0, uf);
1152                                 } else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1153                                         gen_PATCHER_GETSTATIC_CLINIT_CELL(cd, 0, fi);
1154                                 } else {
1155                                         gen_GETSTATIC_CELL(cd, (u1 *)&(fi->value.a), fi);
1156                                 }
1157                                 break;
1158                         }
1159                         }
1160                         break;
1161
1162                 case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
1163                                       /* op1 = type, val.a = field address            */
1164
1165                         {
1166                         fieldinfo *fi = NULL;
1167                         unresolved_field *uf = NULL;
1168
1169                         if (INSTRUCTION_IS_UNRESOLVED(iptr))
1170                                 uf = INSTRUCTION_UNRESOLVED_FIELD(iptr);
1171                         else
1172                                 fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
1173
1174                         switch (iptr->op1) {
1175                         case TYPE_INT:
1176                                 if (fi == NULL) {
1177                                         gen_PATCHER_PUTSTATIC_INT(cd, 0, uf);
1178                                 } else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1179                                         gen_PATCHER_PUTSTATIC_CLINIT_INT(cd, 0, fi);
1180                                 } else {
1181                                         gen_PUTSTATIC_INT(cd, (u1 *)&(fi->value.i), fi);
1182                                 }
1183                                 break;
1184                         case TYPE_FLT:
1185                                 if (fi == NULL) {
1186                                         gen_PATCHER_PUTSTATIC_FLOAT(cd, 0, uf);
1187                                 } else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1188                                         gen_PATCHER_PUTSTATIC_CLINIT_FLOAT(cd, 0, fi);
1189                                 } else {
1190                                         gen_PUTSTATIC_FLOAT(cd, (u1 *)&(fi->value.i), fi);
1191                                 }
1192                                 break;
1193                         case TYPE_LNG:
1194                         case TYPE_DBL:
1195                                 if (fi == NULL) {
1196                                         gen_PATCHER_PUTSTATIC_LONG(cd, 0, uf);
1197                                 } else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1198                                         gen_PATCHER_PUTSTATIC_CLINIT_LONG(cd, 0, fi);
1199                                 } else {
1200                                         gen_PUTSTATIC_LONG(cd, (u1 *)&(fi->value.l), fi);
1201                                 }
1202                                 break;
1203                         case TYPE_ADR:
1204                                 if (fi == NULL) {
1205                                         gen_PATCHER_PUTSTATIC_CELL(cd, 0, uf);
1206                                 } else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1207                                         gen_PATCHER_PUTSTATIC_CLINIT_CELL(cd, 0, fi);
1208                                 } else {
1209                                         gen_PUTSTATIC_CELL(cd, (u1 *)&(fi->value.a), fi);
1210                                 }
1211                                 break;
1212                         }
1213                         }
1214                         break;
1215
1216
1217                 case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
1218                                       /* op1 = type, val.a = field address            */
1219
1220                         {
1221                         fieldinfo *fi = NULL;
1222                         unresolved_field *uf = NULL;
1223
1224                         if (INSTRUCTION_IS_UNRESOLVED(iptr))
1225                                 uf = INSTRUCTION_UNRESOLVED_FIELD(iptr);
1226                         else
1227                                 fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
1228
1229                         switch (iptr->op1) {
1230                         case TYPE_INT:
1231                                 if (fi == NULL) {
1232                                         gen_PATCHER_GETFIELD_INT(cd, 0, uf);
1233                                 } else {
1234                                         gen_GETFIELD_INT(cd, fi->offset, fi);
1235                                 }
1236                                 break;
1237                         case TYPE_FLT:
1238                                 if (fi == NULL) {
1239                                         gen_PATCHER_GETFIELD_FLOAT(cd, 0, uf);
1240                                 } else {
1241                                         gen_GETFIELD_FLOAT(cd, fi->offset, fi);
1242                                 }
1243                                 break;
1244                         case TYPE_LNG:
1245                         case TYPE_DBL:
1246                                 if (fi == NULL) {
1247                                         gen_PATCHER_GETFIELD_LONG(cd, 0, uf);
1248                                 } else {
1249                                         gen_GETFIELD_LONG(cd, fi->offset, fi);
1250                                 }
1251                                 break;
1252                         case TYPE_ADR:
1253                                 if (fi == NULL) {
1254                                         gen_PATCHER_GETFIELD_CELL(cd, 0, uf);
1255                                 } else {
1256                                         gen_GETFIELD_CELL(cd, fi->offset, fi);
1257                                 }
1258                                 break;
1259                         }
1260                         }
1261                         break;
1262
1263                 case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
1264                                       /* op1 = type, val.a = field address            */
1265
1266                         {
1267                         fieldinfo *fi = NULL;
1268                         unresolved_field *uf = NULL;
1269
1270                         if (INSTRUCTION_IS_UNRESOLVED(iptr))
1271                                 uf = INSTRUCTION_UNRESOLVED_FIELD(iptr);
1272                         else
1273                                 fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
1274
1275                         switch (iptr->op1) {
1276                         case TYPE_INT:
1277                                 if (fi == NULL) {
1278                                         gen_PATCHER_PUTFIELD_INT(cd, 0, uf);
1279                                 } else {
1280                                         gen_PUTFIELD_INT(cd, fi->offset, fi);
1281                                 }
1282                                 break;
1283                         case TYPE_FLT:
1284                                 if (fi == NULL) {
1285                                         gen_PATCHER_PUTFIELD_FLOAT(cd, 0, uf);
1286                                 } else {
1287                                         gen_PUTFIELD_FLOAT(cd, fi->offset, fi);
1288                                 }
1289                                 break;
1290                         case TYPE_LNG:
1291                         case TYPE_DBL:
1292                                 if (fi == NULL) {
1293                                         gen_PATCHER_PUTFIELD_LONG(cd, 0, uf);
1294                                 } else {
1295                                         gen_PUTFIELD_LONG(cd, fi->offset, fi);
1296                                 }
1297                                 break;
1298                         case TYPE_ADR:
1299                                 if (fi == NULL) {
1300                                         gen_PATCHER_PUTFIELD_CELL(cd, 0, uf);
1301                                 } else {
1302                                         gen_PUTFIELD_CELL(cd, fi->offset, fi);
1303                                 }
1304                                 break;
1305                         }
1306                         }
1307                         break;
1308
1309
1310                 /* branch operations **************************************************/
1311
1312                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
1313
1314                         gen_ATHROW(cd);
1315                         break;
1316
1317                 case ICMD_GOTO:         /* ... ==> ...                                */
1318                                         /* op1 = target JavaVM pc                     */
1319                         gen_branch(GOTO);
1320                         break;
1321
1322                 case ICMD_JSR:          /* ... ==> ...                                */
1323                                         /* op1 = target JavaVM pc                     */
1324                         gen_branch(JSR);
1325                         break;
1326                         
1327                 case ICMD_RET:          /* ... ==> ...                                */
1328                                         /* op1 = local variable                       */
1329
1330                         gen_RET(cd, index2offset(iptr->op1));
1331                         break;
1332
1333                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
1334                                         /* op1 = target JavaVM pc                     */
1335
1336                         gen_branch(IFNULL);
1337                         break;
1338
1339                 case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
1340                                         /* op1 = target JavaVM pc                     */
1341
1342                         gen_branch(IFNONNULL);
1343                         break;
1344
1345                 case ICMD_IFEQ:         /* ..., value ==> ...                         */
1346                                         /* op1 = target JavaVM pc, val.i = constant   */
1347
1348                         if (iptr->val.i == 0) {
1349                                 gen_branch(IFEQ);
1350                         } else {
1351                                 gen_ICONST(cd, iptr->val.i);
1352                                 gen_branch(IF_ICMPEQ);
1353                         }
1354                         break;
1355
1356                 case ICMD_IFLT:         /* ..., value ==> ...                         */
1357                                         /* op1 = target JavaVM pc, val.i = constant   */
1358
1359                         if (iptr->val.i == 0) {
1360                                 gen_branch(IFLT);
1361                         } else {
1362                                 gen_ICONST(cd, iptr->val.i);
1363                                 gen_branch(IF_ICMPLT);
1364                         }
1365                         break;
1366
1367                 case ICMD_IFLE:         /* ..., value ==> ...                         */
1368                                         /* op1 = target JavaVM pc, val.i = constant   */
1369
1370                         if (iptr->val.i == 0) {
1371                                 gen_branch(IFLE);
1372                         } else {
1373                                 gen_ICONST(cd, iptr->val.i);
1374                                 gen_branch(IF_ICMPLE);
1375                         }
1376                         break;
1377
1378                 case ICMD_IFNE:         /* ..., value ==> ...                         */
1379                                         /* op1 = target JavaVM pc, val.i = constant   */
1380
1381                         if (iptr->val.i == 0) {
1382                                 gen_branch(IFNE);
1383                         } else {
1384                                 gen_ICONST(cd, iptr->val.i);
1385                                 gen_branch(IF_ICMPNE);
1386                         }
1387                         break;
1388
1389                 case ICMD_IFGT:         /* ..., value ==> ...                         */
1390                                         /* op1 = target JavaVM pc, val.i = constant   */
1391
1392                         if (iptr->val.i == 0) {
1393                                 gen_branch(IFGT);
1394                         } else {
1395                                 gen_ICONST(cd, iptr->val.i);
1396                                 gen_branch(IF_ICMPGT);
1397                         }
1398                         break;
1399
1400                 case ICMD_IFGE:         /* ..., value ==> ...                         */
1401                                         /* op1 = target JavaVM pc, val.i = constant   */
1402
1403                         if (iptr->val.i == 0) {
1404                                 gen_branch(IFGE);
1405                         } else {
1406                                 gen_ICONST(cd, iptr->val.i);
1407                                 gen_branch(IF_ICMPGE);
1408                         }
1409                         break;
1410
1411                 case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
1412                                         /* op1 = target JavaVM pc, val.l = constant   */
1413
1414                         gen_LCONST(cd, iptr->val.l);
1415                         gen_branch(IF_LCMPEQ);
1416                         break;
1417
1418                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
1419                                         /* op1 = target JavaVM pc, val.l = constant   */
1420
1421                         gen_LCONST(cd, iptr->val.l);
1422                         gen_branch(IF_LCMPLT);
1423                         break;
1424
1425                 case ICMD_IF_LLE:       /* ..., value ==> ...                         */
1426                                         /* op1 = target JavaVM pc, val.l = constant   */
1427
1428                         gen_LCONST(cd, iptr->val.l);
1429                         gen_branch(IF_LCMPLE);
1430                         break;
1431
1432                 case ICMD_IF_LNE:       /* ..., value ==> ...                         */
1433                                         /* op1 = target JavaVM pc, val.l = constant   */
1434
1435                         gen_LCONST(cd, iptr->val.l);
1436                         gen_branch(IF_LCMPNE);
1437                         break;
1438
1439                 case ICMD_IF_LGT:       /* ..., value ==> ...                         */
1440                                         /* op1 = target JavaVM pc, val.l = constant   */
1441
1442                         gen_LCONST(cd, iptr->val.l);
1443                         gen_branch(IF_LCMPGT);
1444                         break;
1445
1446                 case ICMD_IF_LGE:       /* ..., value ==> ...                         */
1447                                         /* op1 = target JavaVM pc, val.l = constant   */
1448
1449                         gen_LCONST(cd, iptr->val.l);
1450                         gen_branch(IF_LCMPGE);
1451                         break;
1452
1453                 case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
1454                                         /* op1 = target JavaVM pc                     */
1455
1456                         gen_branch(IF_ICMPEQ);
1457                         break;
1458
1459                 case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
1460                                         /* op1 = target JavaVM pc                     */
1461
1462                         gen_branch(IF_LCMPEQ);
1463                         break;
1464
1465                 case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
1466                                         /* op1 = target JavaVM pc                     */
1467
1468                         gen_branch(IF_ACMPEQ);
1469                         break;
1470
1471                 case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
1472                                         /* op1 = target JavaVM pc                     */
1473
1474                         gen_branch(IF_ICMPNE);
1475                         break;
1476
1477                 case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
1478                                         /* op1 = target JavaVM pc                     */
1479
1480                         gen_branch(IF_LCMPNE);
1481                         break;
1482
1483                 case ICMD_IF_ACMPNE:    /* ..., value, value ==> ...                  */
1484                                         /* op1 = target JavaVM pc                     */
1485
1486                         gen_branch(IF_ACMPNE);
1487                         break;
1488
1489                 case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
1490                                         /* op1 = target JavaVM pc                     */
1491
1492                         gen_branch(IF_ICMPLT);
1493                         break;
1494
1495                 case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
1496                                         /* op1 = target JavaVM pc                     */
1497
1498                         gen_branch(IF_LCMPLT);
1499                         break;
1500
1501                 case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
1502                                         /* op1 = target JavaVM pc                     */
1503
1504                         gen_branch(IF_ICMPGT);
1505                         break;
1506
1507                 case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
1508                                         /* op1 = target JavaVM pc                     */
1509
1510                         gen_branch(IF_LCMPGT);
1511                         break;
1512
1513                 case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
1514                                         /* op1 = target JavaVM pc                     */
1515
1516                         gen_branch(IF_ICMPLE);
1517                         break;
1518
1519                 case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
1520                                         /* op1 = target JavaVM pc                     */
1521
1522                         gen_branch(IF_LCMPLE);
1523                         break;
1524
1525                 case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
1526                                         /* op1 = target JavaVM pc                     */
1527
1528                         gen_branch(IF_ICMPGE);
1529                         break;
1530
1531                 case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
1532                                         /* op1 = target JavaVM pc                     */
1533
1534                         gen_branch(IF_LCMPGE);
1535                         break;
1536
1537
1538                 case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
1539                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
1540                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
1541
1542 #if defined(USE_THREADS)
1543                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1544                                 if (m->flags & ACC_STATIC) {
1545                                         gen_ACONST(cd, (java_objectheader *) m->class);
1546                                 } else {
1547                                         gen_ALOAD(cd, 0);
1548                                 }
1549                                 gen_MONITOREXIT(cd);
1550                         }
1551 #endif
1552                         if (opt_verbosecall)
1553                                 gen_TRACERETURN(cd, m);
1554
1555                         gen_IRETURN(cd, index2offset(cd->maxlocals));
1556                         break;
1557
1558                 case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
1559                 case ICMD_DRETURN:      /* ..., retvalue ==> ...                      */
1560
1561 #if defined(USE_THREADS)
1562                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1563                                 if (m->flags & ACC_STATIC) {
1564                                         gen_ACONST(cd, (java_objectheader *) m->class);
1565                                 } else {
1566                                         gen_ALOAD(cd, 0);
1567                                 }
1568                                 gen_MONITOREXIT(cd);
1569                         }
1570 #endif
1571                         if (opt_verbosecall)
1572                                 gen_TRACELRETURN(cd, m);
1573
1574                         gen_LRETURN(cd, index2offset(cd->maxlocals));
1575                         break;
1576
1577                 case ICMD_RETURN:       /* ...  ==> ...                               */
1578
1579 #if defined(USE_THREADS)
1580                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1581                                 if (m->flags & ACC_STATIC) {
1582                                         gen_ACONST(cd, (java_objectheader *) m->class);
1583                                 } else {
1584                                         gen_ALOAD(cd, 0);
1585                                 }
1586                                 gen_MONITOREXIT(cd);
1587                         }
1588 #endif
1589                         if (opt_verbosecall)
1590                                 gen_TRACERETURN(cd, m);
1591
1592                         gen_RETURN(cd, index2offset(cd->maxlocals));
1593                         break;
1594
1595
1596                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
1597                         {
1598                         s4 i, l, *s4ptr;
1599                         void **tptr;
1600
1601                         tptr = (void **) iptr->target;
1602
1603                         s4ptr = iptr->val.a;
1604                         l = s4ptr[1];                          /* low     */
1605                         i = s4ptr[2];                          /* high    */
1606                         
1607                         i = i - l + 1;
1608
1609                         /* arguments: low, range, datasegment address, table
1610                        offset in datasegment, default target */
1611
1612                         gen_TABLESWITCH(cd, l, i, NULL, 0, NULL);
1613
1614                         /* actually -3 cells offset */
1615
1616                         cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1617                         dseg_adddata(cd);
1618                         cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1619
1620                         codegen_addreference(cd, (basicblock *) tptr[0]);
1621
1622                         /* build jump table top down and use address of lowest entry */
1623
1624                         tptr += i;
1625
1626                         while (--i >= 0) {
1627                                 dseg_addtarget(cd, (basicblock *) tptr[0]); 
1628                                 --tptr;
1629                         }
1630                         }
1631
1632                         /* length of dataseg after last dseg_addtarget is used by load */
1633                         ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1634                         break;
1635
1636
1637                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
1638                         {
1639                         s4 i, *s4ptr;
1640                         void **tptr;
1641
1642                         tptr = (void **) iptr->target;
1643
1644                         s4ptr = iptr->val.a;
1645
1646                         /* s4ptr[0] is equal to tptr[0] */
1647                         i = s4ptr[1];                          /* count    */
1648                         
1649                         /* arguments: count, datasegment address, table offset in         */
1650                         /* datasegment, default target                                    */
1651                         gen_LOOKUPSWITCH(cd, i, NULL, 0, NULL);
1652
1653                         /* actually -3 cells offset */
1654
1655                         cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1656                         dseg_adddata(cd);
1657                         cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1658
1659                         codegen_addreference(cd, (basicblock *) tptr[0]);
1660
1661                         /* build jump table top down and use address of lowest entry */
1662
1663                         tptr += i;
1664                         s4ptr += i * 2;
1665
1666                         while (--i >= 0) {
1667                                 dseg_addtarget(cd, (basicblock *) tptr[0]); 
1668                                 dseg_addaddress(cd, s4ptr[0]);
1669                                 --tptr;
1670                                 s4ptr -= 2;
1671                         }
1672                         }
1673
1674                         /* length of dataseg after last dseg_addtarget is used by load */
1675                         ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1676                         break;
1677
1678
1679                 case ICMD_BUILTIN:      /* ..., arg1, arg2, arg3 ==> ...              */
1680                                         /* op1 = arg count val.a = builtintable entry */
1681                         bte = iptr->val.a;
1682
1683                         for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
1684                                 builtin_gen *bg = &builtin_gen_table[i];
1685                                 if (bg->builtin == bte->fp) {
1686                                         (bg->gen)(cd);
1687                                         goto gen_builtin_end;
1688                                 }
1689                         }
1690                         assert(0);
1691                 gen_builtin_end:
1692                         break;
1693
1694                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
1695                                         /* op1 = arg count, val.a = method pointer    */
1696
1697                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1698                                 um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
1699                                 md = um->methodref->parseddesc.md;
1700                                 gen_PATCHER_INVOKESTATIC(cd, 0, md->paramslots, um);
1701
1702                         } else {
1703                                 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
1704                                 md = lm->parseddesc;
1705                                 gen_INVOKESTATIC(cd, (Inst **)lm->stubroutine, md->paramslots, lm);
1706                         }
1707                         break;
1708
1709                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1710
1711                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1712                                 um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
1713                                 md = um->methodref->parseddesc.md;
1714                                 gen_PATCHER_INVOKESPECIAL(cd, 0, md->paramslots, um);
1715
1716                         } else {
1717                                 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
1718                                 md = lm->parseddesc;
1719                                 gen_INVOKESPECIAL(cd, (Inst **)lm->stubroutine, md->paramslots, lm);
1720                         }
1721                         break;
1722
1723                 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
1724
1725                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1726                                 um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
1727                                 md = um->methodref->parseddesc.md;
1728                                 gen_PATCHER_INVOKEVIRTUAL(cd, 0, md->paramslots, um);
1729
1730                         } else {
1731                                 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
1732                                 md = lm->parseddesc;
1733
1734                                 s1 = OFFSET(vftbl_t, table[0]) +
1735                                         sizeof(methodptr) * lm->vftblindex;
1736
1737                                 gen_INVOKEVIRTUAL(cd, s1, md->paramslots, lm);
1738                         }
1739                         break;
1740
1741                 case ICMD_INVOKEINTERFACE:/* op1 = arg count, val.a = method pointer  */
1742
1743                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1744                                 um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
1745                                 md = um->methodref->parseddesc.md;
1746                                 gen_PATCHER_INVOKEINTERFACE(cd, 0, 0, md->paramslots, um);
1747
1748                         } else {
1749                                 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
1750                                 md = lm->parseddesc;
1751
1752                                 s1 = OFFSET(vftbl_t, interfacetable[0]) -
1753                                         sizeof(methodptr*) * lm->class->index;
1754
1755                                 s2 = sizeof(methodptr) * (lm - lm->class->methods);
1756
1757                                 gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
1758                         }
1759                         break;
1760
1761
1762                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
1763                                       /* op1:   0 == array, 1 == class                */
1764                                       /* val.a: (classinfo *) superclass              */
1765
1766                         if (iptr->op1 == 1) {
1767                                 if (iptr->val.a == NULL)
1768                                         gen_PATCHER_CHECKCAST(cd, NULL, iptr->target);
1769                                 else
1770                                         gen_CHECKCAST(cd, iptr->val.a, NULL);
1771                         } else {
1772                                 if (iptr->val.a == NULL)
1773                                         gen_PATCHER_ARRAYCHECKCAST(cd, NULL, iptr->target);
1774                                 else
1775                                         gen_ARRAYCHECKCAST(cd, iptr->val.a, NULL);
1776                         }
1777                         break;
1778
1779                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
1780                                       /* op1:   0 == array, 1 == class                */
1781                                       /* val.a: (classinfo *) superclass              */
1782
1783                         if (iptr->val.a == NULL)
1784                                 gen_PATCHER_INSTANCEOF(cd, NULL, iptr->target);
1785                         else
1786                                 gen_INSTANCEOF(cd, iptr->val.a, iptr->target);
1787                         break;
1788
1789                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
1790                                       /* op1 = dimension, val.a = class               */
1791
1792                         if (iptr->val.a == NULL) {
1793                                 gen_PATCHER_MULTIANEWARRAY(cd, NULL, iptr->op1, iptr->target);
1794                         } else {
1795                                 gen_MULTIANEWARRAY(cd, iptr->val.a, iptr->op1, NULL);
1796                         }
1797                         break;
1798
1799                 default:
1800                         *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
1801                         return false;
1802         } /* switch */
1803                 
1804         } /* for instruction */
1805
1806         gen_BBEND;
1807
1808         } /* if (bptr->flags >= BBREACHED) */
1809         } /* for basic block */
1810
1811         dseg_createlinenumbertable(cd);
1812
1813         codegen_finish(jd);
1814
1815 #ifdef VM_PROFILING
1816         vm_block_insert(jd->code->mcode + jd->code->mcodelength);
1817 #endif
1818
1819         /* branch resolving (walk through all basic blocks) */
1820
1821         for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
1822                 branchref *brefs;
1823
1824                 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
1825                         gen_resolveanybranch(((u1*) jd->code->entrypoint) + brefs->branchpos,
1826                                              ((u1 *)jd->code->entrypoint) + bptr->mpc);
1827                 }
1828         }
1829
1830         /* everything's ok */
1831
1832         return true;
1833 }
1834
1835
1836 /* createcompilerstub **********************************************************
1837
1838    Creates a stub routine which calls the compiler.
1839
1840    A stub consists of:
1841
1842    +-------------+
1843    | methodinfo* |
1844    +-------------+ <-- stub
1845    | codeptr     |
1846    +-------------+
1847    | maxlocals   |
1848    +-------------+
1849    | TRANSLATE   |
1850    +-------------+
1851    | methodinfo  |
1852    +-------------+
1853
1854    codeptr points either to TRANSLATE or to the translated threaded code
1855
1856    all methods are called indirectly through methodptr
1857
1858 *******************************************************************************/
1859
1860 #define COMPILERSTUB_DATASIZE    1
1861 #define COMPILERSTUB_CODESIZE    4
1862
1863 #define COMPILERSTUB_SIZE        COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
1864
1865
1866 u1 *intrp_createcompilerstub(methodinfo *m)
1867 {
1868         Inst        *s;
1869         Inst        *d;
1870         codegendata *cd;
1871         s4           dumpsize;
1872
1873         s = CNEW(Inst, COMPILERSTUB_SIZE);
1874
1875         /* set data pointer and code pointer */
1876
1877         d = s;
1878         s = s + COMPILERSTUB_DATASIZE;
1879
1880         /* Store the methodinfo* in the same place as in the methodheader
1881            for compiled methods. */
1882
1883         d[0] = (Inst *) m;
1884
1885         /* mark start of dump memory area */
1886
1887         dumpsize = dump_size();
1888         
1889         cd = DNEW(codegendata);
1890     cd->mcodeptr = (u1 *) s;
1891         cd->lastinstwithoutdispatch = ~0;
1892         cd->superstarts = NULL;
1893
1894         genarg_ainst(cd, s + 2);
1895
1896         if (m->flags & ACC_NATIVE) {
1897                 genarg_i(cd, m->parseddesc->paramslots);
1898         } else {
1899                 genarg_i(cd, m->maxlocals);
1900         }
1901
1902         gen_BBSTART;
1903         gen_TRANSLATE(cd, m);
1904         gen_BBEND;
1905         
1906 #ifdef VM_PROFILING
1907         vm_block_insert(cd->mcodeptr);
1908 #endif
1909
1910 #if defined(ENABLE_STATISTICS)
1911         if (opt_stat)
1912                 count_cstub_len += COMPILERSTUB_SIZE;
1913 #endif
1914
1915         /* release dump area */
1916
1917         dump_release(dumpsize);
1918         
1919         return (u1 *) s;
1920 }
1921
1922
1923 #if defined(WITH_FFI)
1924 static ffi_type *cacaotype2ffitype(s4 cacaotype)
1925 {
1926         switch (cacaotype) {
1927         case TYPE_INT:
1928 #if SIZEOF_VOID_P == 8
1929                 return &ffi_type_sint64;
1930 #else
1931                 return &ffi_type_sint32;
1932 #endif
1933         case TYPE_LNG:
1934                 return &ffi_type_sint64;
1935         case TYPE_FLT:
1936                 return &ffi_type_float;
1937         case TYPE_DBL:
1938                 return &ffi_type_double;
1939         case TYPE_ADR:
1940                 return &ffi_type_pointer;
1941         case TYPE_VOID:
1942                 return &ffi_type_void;
1943         default:
1944                 assert(false);
1945         }
1946 }
1947 #endif
1948
1949
1950 /* native stub:
1951 +---------+
1952 |NATIVECALL|
1953 +---------+
1954 |methodinf|
1955 +---------+
1956 |function |
1957 +---------+
1958 |cif      |
1959 +---------+
1960 */
1961
1962 #if defined(WITH_FFI)
1963 static ffi_cif *createnativecif(methodinfo *m, methoddesc *nmd)
1964 {
1965         methoddesc  *md = m->parseddesc; 
1966         ffi_cif     *pcif = NEW(ffi_cif);
1967         ffi_type   **types = MNEW(ffi_type *, nmd->paramcount);
1968         ffi_type   **ptypes = types;
1969         s4           i;
1970
1971         /* pass env pointer */
1972
1973         *ptypes++ = &ffi_type_pointer;
1974
1975         /* for static methods, pass class pointer */
1976
1977         if (m->flags & ACC_STATIC)
1978                 *ptypes++ = &ffi_type_pointer;
1979
1980         /* pass parameter to native function */
1981
1982         for (i = 0; i < md->paramcount; i++)
1983                 *ptypes++ = cacaotype2ffitype(md->paramtypes[i].type);
1984
1985         assert(ptypes - types == nmd->paramcount);
1986
1987     if (ffi_prep_cif(pcif, FFI_DEFAULT_ABI, nmd->paramcount, cacaotype2ffitype(md->returntype.type), types) != FFI_OK)
1988                 assert(0);
1989
1990         return pcif;
1991 }
1992 #endif
1993
1994
1995 u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
1996 {
1997         methodinfo   *m;
1998         codegendata  *cd;
1999         registerdata *rd;
2000 #if defined(WITH_FFI)
2001         ffi_cif *cif;
2002 #else
2003         u1      *cif;
2004 #endif
2005
2006         /* get required compiler data */
2007
2008         m  = jd->m;
2009         cd = jd->cd;
2010         rd = jd->rd;
2011
2012         /* create method header */
2013
2014         (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
2015         (void) dseg_adds4(cd, nmd->paramslots * SIZEOF_VOID_P); /* FrameSize      */
2016         (void) dseg_adds4(cd, 0);                               /* IsSync         */
2017         (void) dseg_adds4(cd, 0);                               /* IsLeaf         */
2018         (void) dseg_adds4(cd, 0);                               /* IntSave        */
2019         (void) dseg_adds4(cd, 0);                               /* FltSave        */
2020         dseg_addlinenumbertablesize(cd);
2021         (void) dseg_adds4(cd, 0);                               /* ExTableSize    */
2022
2023 #if defined(WITH_FFI)
2024         /* prepare ffi cif structure */
2025
2026         cif = createnativecif(m, nmd);
2027 #else
2028         cif = NULL;
2029 #endif
2030
2031         gen_BBSTART;
2032
2033         if (opt_verbosecall)
2034                 gen_TRACECALL(cd, m);
2035
2036         if (f == NULL) {
2037                 gen_PATCHER_NATIVECALL(cd, m, f, (u1 *)cif);
2038         } else {
2039                 if (opt_verbosecall)
2040                         gen_TRACENATIVECALL(cd, m, f, (u1 *)cif);
2041                 else
2042                         gen_NATIVECALL(cd, m, f, (u1 *)cif);
2043         }
2044
2045         gen_BBEND;
2046
2047         codegen_finish(jd);
2048
2049 #ifdef VM_PROFILING
2050         vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2051 #endif
2052
2053         return jd->code->entrypoint;
2054 }
2055
2056
2057 /* call jni function */
2058 Cell *nativecall(functionptr f, methodinfo *m, Cell *sp, Inst *ra, Cell *fp, u1 *addrcif)
2059 {
2060 #if defined(WITH_FFCALL)
2061         av_alist alist;
2062         methoddesc *md;
2063         Cell *p;
2064         Cell *endsp;
2065         s4 i;
2066
2067         struct {
2068                 stackframeinfo sfi;
2069                 localref_table lrt;
2070         } s;
2071
2072         md = m->parseddesc;
2073
2074         switch (md->returntype.type) {
2075         case TYPE_INT:
2076                 endsp = sp - 1 + md->paramslots;
2077                 av_start_long(alist, f, endsp);
2078                 break;
2079         case TYPE_LNG:
2080                 endsp = sp - 2 + md->paramslots;
2081                 av_start_longlong(alist, f, endsp);
2082                 break;
2083         case TYPE_FLT:
2084                 endsp = sp - 1 + md->paramslots;
2085                 av_start_float(alist, f, endsp);
2086                 break;
2087         case TYPE_DBL:
2088                 endsp = sp - 2 + md->paramslots;
2089                 av_start_double(alist, f, endsp);
2090                 break;
2091         case TYPE_ADR:
2092                 endsp = sp - 1 + md->paramslots;
2093                 av_start_ptr(alist, f, void *, endsp);
2094                 break;
2095         case TYPE_VOID:
2096                 endsp = sp + md->paramslots;
2097                 av_start_void(alist, f);
2098                 break;
2099         default:
2100                 assert(false);
2101         }
2102
2103         av_ptr(alist, _Jv_JNIEnv *, _Jv_env);
2104
2105         if (m->flags & ACC_STATIC)
2106                 av_ptr(alist, classinfo *, m->class);
2107
2108         for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2109                 switch (md->paramtypes[i].type) {
2110                 case TYPE_INT:
2111                         p -= 1;
2112                         av_long(alist, *p);
2113                         break;
2114                 case TYPE_LNG:
2115                         p -= 2;
2116                         av_longlong(alist, *(s8 *)p);
2117                         break;
2118                 case TYPE_FLT:
2119                         p -= 1;
2120                         av_float(alist, *((float *) p));
2121                         break;
2122                 case TYPE_DBL:
2123                         p -= 2;
2124                         av_double(alist, *(double *) p);
2125                         break;
2126                 case TYPE_ADR:
2127                         p -= 1;
2128                         av_ptr(alist, void *, *(void **) p);
2129                         break;
2130                 default:
2131                         assert(false);
2132                 }
2133         }
2134
2135         global_sp = sp;
2136
2137         /* create stackframe info structure */
2138
2139         codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2140                                                           (u1 *) fp, (u1 *) ra);
2141
2142         av_call(alist);
2143
2144         codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2145
2146         CLEAR_global_sp;
2147
2148         return endsp;
2149 #elif defined(WITH_FFI)
2150         methoddesc  *md = m->parseddesc; 
2151         ffi_cif     *pcif;
2152         void        *values[md->paramcount + 2];
2153         void       **pvalues = values;
2154         Cell        *p;
2155         Cell        *endsp;
2156         s4           i;
2157         _Jv_JNIEnv  *penv;
2158
2159         struct {
2160                 stackframeinfo sfi;
2161                 localref_table lrt;
2162         } s;
2163
2164         pcif = (ffi_cif *) addrcif;
2165
2166         /* pass env pointer */
2167
2168         penv = (_Jv_JNIEnv *) _Jv_env;
2169         *pvalues++ = &penv;
2170
2171         /* for static methods, pass class pointer */
2172
2173         if (m->flags & ACC_STATIC)
2174                 *pvalues++ = &m->class;
2175
2176         /* pass parameter to native function */
2177
2178         for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2179                 if (IS_2_WORD_TYPE(md->paramtypes[i].type))
2180                         p -= 2;
2181                 else
2182                         p--;
2183
2184                 *pvalues++ = p;
2185         }
2186
2187         /* calculate position of return value */
2188
2189         if (md->returntype.type == TYPE_VOID)
2190                 endsp = sp + md->paramslots;
2191         else
2192                 endsp = sp - (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1) + md->paramslots;
2193
2194         global_sp = sp;
2195
2196         /* create stackframe info structure */
2197
2198         codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2199                                                           (u1 *) fp, (u1 *) ra);
2200
2201         ffi_call(pcif, FFI_FN(f), endsp, values);
2202
2203         codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2204
2205         CLEAR_global_sp;
2206
2207         return endsp;
2208 #endif
2209 }
2210
2211
2212 u1 *createcalljavafunction(methodinfo *m)
2213 {
2214         methodinfo         *tmpm;
2215         u1                 *entrypoint;
2216         jitdata            *jd;
2217         codegendata        *cd;
2218         registerdata       *rd;
2219         s4                  dumpsize;
2220         methoddesc         *md;
2221
2222         /* mark dump memory */
2223
2224         dumpsize = dump_size();
2225
2226         /* allocate memory */
2227
2228         jd = DNEW(jitdata);
2229
2230         tmpm = DNEW(methodinfo);
2231         cd = DNEW(codegendata);
2232         rd = DNEW(registerdata);
2233
2234         jd->m = tmpm;
2235         jd->flags = 0;
2236         jd->cd = cd;
2237         jd->rd = rd;
2238
2239         /* Allocate codeinfo memory from the heap as we need to keep them. */
2240
2241         jd->code = code_codeinfo_new(tmpm); /* XXX check allocation */
2242
2243         /* setup code generation stuff */
2244
2245         MSET(tmpm, 0, u1, sizeof(methodinfo));
2246
2247         codegen_setup(jd);
2248
2249         md = m->parseddesc;
2250
2251         /* create method header */
2252
2253         (void) dseg_addaddress(cd, NULL);                       /* MethodPointer  */
2254         (void) dseg_adds4(cd, md->paramslots * SIZEOF_VOID_P);  /* FrameSize      */
2255         (void) dseg_adds4(cd, 0);                               /* IsSync         */
2256         (void) dseg_adds4(cd, 0);                               /* IsLeaf         */
2257         (void) dseg_adds4(cd, 0);                               /* IntSave        */
2258         (void) dseg_adds4(cd, 0);                               /* FltSave        */
2259         dseg_addlinenumbertablesize(cd);
2260         (void) dseg_adds4(cd, 0);                               /* ExTableSize    */
2261
2262
2263         /* generate code */
2264         
2265         gen_BBSTART;
2266         gen_INVOKESTATIC(cd, (Inst **)m->stubroutine, md->paramslots, 0);
2267         gen_END(cd);
2268
2269         gen_BBEND;
2270
2271         codegen_finish(jd);
2272
2273 #ifdef VM_PROFILING
2274         vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2275 #endif
2276         entrypoint = jd->code->entrypoint;
2277
2278         /* release memory */
2279
2280         dump_release(dumpsize);
2281
2282         return entrypoint;
2283 }
2284
2285
2286 /*
2287  * These are local overrides for various environment variables in Emacs.
2288  * Please do not remove this and leave it at the end of the file, where
2289  * Emacs will automagically detect them.
2290  * ---------------------------------------------------------------------
2291  * Local variables:
2292  * mode: c
2293  * indent-tabs-mode: t
2294  * c-basic-offset: 4
2295  * tab-width: 4
2296  * End:
2297  * vim:noexpandtab:sw=4:ts=4:
2298  */