* src/vm/jit/alpha/codegen.h: Removed M_COPY.
[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 5632 2006-10-02 13:43:15Z 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(ENABLE_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, jd->code);                  /* CodeinfoPointer */
316         (void) dseg_adds4(cd, m->maxlocals * SIZEOF_VOID_P);    /* FrameSize      */
317
318 #if defined(ENABLE_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.any);
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(ENABLE_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                 case ICMD_RET:          /* ... ==> ...                                */
1319                                         /* op1 = target JavaVM pc                     */
1320                         gen_branch(GOTO);
1321                         break;
1322
1323                 case ICMD_JSR:          /* ... ==> ...                                */
1324                                         /* op1 = target JavaVM pc                     */
1325                         gen_branch(JSR);
1326                         break;
1327                         
1328                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
1329                                         /* op1 = target JavaVM pc                     */
1330
1331                         gen_branch(IFNULL);
1332                         break;
1333
1334                 case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
1335                                         /* op1 = target JavaVM pc                     */
1336
1337                         gen_branch(IFNONNULL);
1338                         break;
1339
1340                 case ICMD_IFEQ:         /* ..., value ==> ...                         */
1341                                         /* op1 = target JavaVM pc, val.i = constant   */
1342
1343                         if (iptr->val.i == 0) {
1344                                 gen_branch(IFEQ);
1345                         } else {
1346                                 gen_ICONST(cd, iptr->val.i);
1347                                 gen_branch(IF_ICMPEQ);
1348                         }
1349                         break;
1350
1351                 case ICMD_IFLT:         /* ..., value ==> ...                         */
1352                                         /* op1 = target JavaVM pc, val.i = constant   */
1353
1354                         if (iptr->val.i == 0) {
1355                                 gen_branch(IFLT);
1356                         } else {
1357                                 gen_ICONST(cd, iptr->val.i);
1358                                 gen_branch(IF_ICMPLT);
1359                         }
1360                         break;
1361
1362                 case ICMD_IFLE:         /* ..., value ==> ...                         */
1363                                         /* op1 = target JavaVM pc, val.i = constant   */
1364
1365                         if (iptr->val.i == 0) {
1366                                 gen_branch(IFLE);
1367                         } else {
1368                                 gen_ICONST(cd, iptr->val.i);
1369                                 gen_branch(IF_ICMPLE);
1370                         }
1371                         break;
1372
1373                 case ICMD_IFNE:         /* ..., value ==> ...                         */
1374                                         /* op1 = target JavaVM pc, val.i = constant   */
1375
1376                         if (iptr->val.i == 0) {
1377                                 gen_branch(IFNE);
1378                         } else {
1379                                 gen_ICONST(cd, iptr->val.i);
1380                                 gen_branch(IF_ICMPNE);
1381                         }
1382                         break;
1383
1384                 case ICMD_IFGT:         /* ..., value ==> ...                         */
1385                                         /* op1 = target JavaVM pc, val.i = constant   */
1386
1387                         if (iptr->val.i == 0) {
1388                                 gen_branch(IFGT);
1389                         } else {
1390                                 gen_ICONST(cd, iptr->val.i);
1391                                 gen_branch(IF_ICMPGT);
1392                         }
1393                         break;
1394
1395                 case ICMD_IFGE:         /* ..., value ==> ...                         */
1396                                         /* op1 = target JavaVM pc, val.i = constant   */
1397
1398                         if (iptr->val.i == 0) {
1399                                 gen_branch(IFGE);
1400                         } else {
1401                                 gen_ICONST(cd, iptr->val.i);
1402                                 gen_branch(IF_ICMPGE);
1403                         }
1404                         break;
1405
1406                 case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
1407                                         /* op1 = target JavaVM pc, val.l = constant   */
1408
1409                         gen_LCONST(cd, iptr->val.l);
1410                         gen_branch(IF_LCMPEQ);
1411                         break;
1412
1413                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
1414                                         /* op1 = target JavaVM pc, val.l = constant   */
1415
1416                         gen_LCONST(cd, iptr->val.l);
1417                         gen_branch(IF_LCMPLT);
1418                         break;
1419
1420                 case ICMD_IF_LLE:       /* ..., value ==> ...                         */
1421                                         /* op1 = target JavaVM pc, val.l = constant   */
1422
1423                         gen_LCONST(cd, iptr->val.l);
1424                         gen_branch(IF_LCMPLE);
1425                         break;
1426
1427                 case ICMD_IF_LNE:       /* ..., value ==> ...                         */
1428                                         /* op1 = target JavaVM pc, val.l = constant   */
1429
1430                         gen_LCONST(cd, iptr->val.l);
1431                         gen_branch(IF_LCMPNE);
1432                         break;
1433
1434                 case ICMD_IF_LGT:       /* ..., value ==> ...                         */
1435                                         /* op1 = target JavaVM pc, val.l = constant   */
1436
1437                         gen_LCONST(cd, iptr->val.l);
1438                         gen_branch(IF_LCMPGT);
1439                         break;
1440
1441                 case ICMD_IF_LGE:       /* ..., value ==> ...                         */
1442                                         /* op1 = target JavaVM pc, val.l = constant   */
1443
1444                         gen_LCONST(cd, iptr->val.l);
1445                         gen_branch(IF_LCMPGE);
1446                         break;
1447
1448                 case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
1449                                         /* op1 = target JavaVM pc                     */
1450
1451                         gen_branch(IF_ICMPEQ);
1452                         break;
1453
1454                 case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
1455                                         /* op1 = target JavaVM pc                     */
1456
1457                         gen_branch(IF_LCMPEQ);
1458                         break;
1459
1460                 case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
1461                                         /* op1 = target JavaVM pc                     */
1462
1463                         gen_branch(IF_ACMPEQ);
1464                         break;
1465
1466                 case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
1467                                         /* op1 = target JavaVM pc                     */
1468
1469                         gen_branch(IF_ICMPNE);
1470                         break;
1471
1472                 case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
1473                                         /* op1 = target JavaVM pc                     */
1474
1475                         gen_branch(IF_LCMPNE);
1476                         break;
1477
1478                 case ICMD_IF_ACMPNE:    /* ..., value, value ==> ...                  */
1479                                         /* op1 = target JavaVM pc                     */
1480
1481                         gen_branch(IF_ACMPNE);
1482                         break;
1483
1484                 case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
1485                                         /* op1 = target JavaVM pc                     */
1486
1487                         gen_branch(IF_ICMPLT);
1488                         break;
1489
1490                 case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
1491                                         /* op1 = target JavaVM pc                     */
1492
1493                         gen_branch(IF_LCMPLT);
1494                         break;
1495
1496                 case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
1497                                         /* op1 = target JavaVM pc                     */
1498
1499                         gen_branch(IF_ICMPGT);
1500                         break;
1501
1502                 case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
1503                                         /* op1 = target JavaVM pc                     */
1504
1505                         gen_branch(IF_LCMPGT);
1506                         break;
1507
1508                 case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
1509                                         /* op1 = target JavaVM pc                     */
1510
1511                         gen_branch(IF_ICMPLE);
1512                         break;
1513
1514                 case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
1515                                         /* op1 = target JavaVM pc                     */
1516
1517                         gen_branch(IF_LCMPLE);
1518                         break;
1519
1520                 case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
1521                                         /* op1 = target JavaVM pc                     */
1522
1523                         gen_branch(IF_ICMPGE);
1524                         break;
1525
1526                 case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
1527                                         /* op1 = target JavaVM pc                     */
1528
1529                         gen_branch(IF_LCMPGE);
1530                         break;
1531
1532
1533                 case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
1534                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
1535                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
1536
1537 #if defined(ENABLE_THREADS)
1538                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1539                                 if (m->flags & ACC_STATIC) {
1540                                         gen_ACONST(cd, (java_objectheader *) m->class);
1541                                 } else {
1542                                         gen_ALOAD(cd, 0);
1543                                 }
1544                                 gen_MONITOREXIT(cd);
1545                         }
1546 #endif
1547                         if (opt_verbosecall)
1548                                 gen_TRACERETURN(cd, m);
1549
1550                         gen_IRETURN(cd, index2offset(cd->maxlocals));
1551                         break;
1552
1553                 case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
1554                 case ICMD_DRETURN:      /* ..., retvalue ==> ...                      */
1555
1556 #if defined(ENABLE_THREADS)
1557                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1558                                 if (m->flags & ACC_STATIC) {
1559                                         gen_ACONST(cd, (java_objectheader *) m->class);
1560                                 } else {
1561                                         gen_ALOAD(cd, 0);
1562                                 }
1563                                 gen_MONITOREXIT(cd);
1564                         }
1565 #endif
1566                         if (opt_verbosecall)
1567                                 gen_TRACELRETURN(cd, m);
1568
1569                         gen_LRETURN(cd, index2offset(cd->maxlocals));
1570                         break;
1571
1572                 case ICMD_RETURN:       /* ...  ==> ...                               */
1573
1574 #if defined(ENABLE_THREADS)
1575                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1576                                 if (m->flags & ACC_STATIC) {
1577                                         gen_ACONST(cd, (java_objectheader *) m->class);
1578                                 } else {
1579                                         gen_ALOAD(cd, 0);
1580                                 }
1581                                 gen_MONITOREXIT(cd);
1582                         }
1583 #endif
1584                         if (opt_verbosecall)
1585                                 gen_TRACERETURN(cd, m);
1586
1587                         gen_RETURN(cd, index2offset(cd->maxlocals));
1588                         break;
1589
1590
1591                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
1592                         {
1593                         s4 i, l, *s4ptr;
1594                         void **tptr;
1595
1596                         tptr = (void **) iptr->target;
1597
1598                         s4ptr = iptr->val.a;
1599                         l = s4ptr[1];                          /* low     */
1600                         i = s4ptr[2];                          /* high    */
1601                         
1602                         i = i - l + 1;
1603
1604                         /* arguments: low, range, datasegment address, table
1605                        offset in datasegment, default target */
1606
1607                         gen_TABLESWITCH(cd, l, i, NULL, 0, NULL);
1608
1609                         /* actually -3 cells offset */
1610
1611                         cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1612                         dseg_adddata(cd);
1613                         cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1614
1615                         codegen_addreference(cd, (basicblock *) tptr[0]);
1616
1617                         /* build jump table top down and use address of lowest entry */
1618
1619                         tptr += i;
1620
1621                         while (--i >= 0) {
1622                                 dseg_addtarget(cd, (basicblock *) tptr[0]); 
1623                                 --tptr;
1624                         }
1625                         }
1626
1627                         /* length of dataseg after last dseg_addtarget is used by load */
1628                         ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1629                         break;
1630
1631
1632                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
1633                         {
1634                         s4 i, *s4ptr;
1635                         void **tptr;
1636
1637                         tptr = (void **) iptr->target;
1638
1639                         s4ptr = iptr->val.a;
1640
1641                         /* s4ptr[0] is equal to tptr[0] */
1642                         i = s4ptr[1];                          /* count    */
1643                         
1644                         /* arguments: count, datasegment address, table offset in         */
1645                         /* datasegment, default target                                    */
1646                         gen_LOOKUPSWITCH(cd, i, NULL, 0, NULL);
1647
1648                         /* actually -3 cells offset */
1649
1650                         cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1651                         dseg_adddata(cd);
1652                         cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1653
1654                         codegen_addreference(cd, (basicblock *) tptr[0]);
1655
1656                         /* build jump table top down and use address of lowest entry */
1657
1658                         tptr += i;
1659                         s4ptr += i * 2;
1660
1661                         while (--i >= 0) {
1662                                 dseg_addtarget(cd, (basicblock *) tptr[0]); 
1663                                 dseg_addaddress(cd, s4ptr[0]);
1664                                 --tptr;
1665                                 s4ptr -= 2;
1666                         }
1667                         }
1668
1669                         /* length of dataseg after last dseg_addtarget is used by load */
1670                         ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1671                         break;
1672
1673
1674                 case ICMD_BUILTIN:      /* ..., arg1, arg2, arg3 ==> ...              */
1675                                         /* op1 = arg count val.a = builtintable entry */
1676                         bte = iptr->val.a;
1677
1678                         for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
1679                                 builtin_gen *bg = &builtin_gen_table[i];
1680                                 if (bg->builtin == bte->fp) {
1681                                         (bg->gen)(cd);
1682                                         goto gen_builtin_end;
1683                                 }
1684                         }
1685                         assert(0);
1686                 gen_builtin_end:
1687                         break;
1688
1689                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
1690                                         /* op1 = arg count, val.a = method pointer    */
1691
1692                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1693                                 um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
1694                                 md = um->methodref->parseddesc.md;
1695                                 gen_PATCHER_INVOKESTATIC(cd, 0, md->paramslots, um);
1696
1697                         } else {
1698                                 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
1699                                 md = lm->parseddesc;
1700                                 gen_INVOKESTATIC(cd, (Inst **)lm->stubroutine, md->paramslots, lm);
1701                         }
1702                         break;
1703
1704                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1705
1706                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1707                                 um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
1708                                 md = um->methodref->parseddesc.md;
1709                                 gen_PATCHER_INVOKESPECIAL(cd, 0, md->paramslots, um);
1710
1711                         } else {
1712                                 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
1713                                 md = lm->parseddesc;
1714                                 gen_INVOKESPECIAL(cd, (Inst **)lm->stubroutine, md->paramslots, lm);
1715                         }
1716                         break;
1717
1718                 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
1719
1720                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1721                                 um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
1722                                 md = um->methodref->parseddesc.md;
1723                                 gen_PATCHER_INVOKEVIRTUAL(cd, 0, md->paramslots, um);
1724
1725                         } else {
1726                                 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
1727                                 md = lm->parseddesc;
1728
1729                                 s1 = OFFSET(vftbl_t, table[0]) +
1730                                         sizeof(methodptr) * lm->vftblindex;
1731
1732                                 gen_INVOKEVIRTUAL(cd, s1, md->paramslots, lm);
1733                         }
1734                         break;
1735
1736                 case ICMD_INVOKEINTERFACE:/* op1 = arg count, val.a = method pointer  */
1737
1738                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1739                                 um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
1740                                 md = um->methodref->parseddesc.md;
1741                                 gen_PATCHER_INVOKEINTERFACE(cd, 0, 0, md->paramslots, um);
1742
1743                         } else {
1744                                 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
1745                                 md = lm->parseddesc;
1746
1747                                 s1 = OFFSET(vftbl_t, interfacetable[0]) -
1748                                         sizeof(methodptr*) * lm->class->index;
1749
1750                                 s2 = sizeof(methodptr) * (lm - lm->class->methods);
1751
1752                                 gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
1753                         }
1754                         break;
1755
1756
1757                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
1758                                       /* op1:   0 == array, 1 == class                */
1759                                       /* val.a: (classinfo *) superclass              */
1760
1761                         if (iptr->op1 == 1) {
1762                                 if (iptr->val.a == NULL)
1763                                         gen_PATCHER_CHECKCAST(cd, NULL, iptr->target);
1764                                 else
1765                                         gen_CHECKCAST(cd, iptr->val.a, NULL);
1766                         } else {
1767                                 if (iptr->val.a == NULL)
1768                                         gen_PATCHER_ARRAYCHECKCAST(cd, NULL, iptr->target);
1769                                 else
1770                                         gen_ARRAYCHECKCAST(cd, iptr->val.a, NULL);
1771                         }
1772                         break;
1773
1774                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
1775                                       /* op1:   0 == array, 1 == class                */
1776                                       /* val.a: (classinfo *) superclass              */
1777
1778                         if (iptr->val.a == NULL)
1779                                 gen_PATCHER_INSTANCEOF(cd, NULL, iptr->target);
1780                         else
1781                                 gen_INSTANCEOF(cd, iptr->val.a, iptr->target);
1782                         break;
1783
1784                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
1785                                       /* op1 = dimension, val.a = class               */
1786
1787                         if (iptr->val.a == NULL) {
1788                                 gen_PATCHER_MULTIANEWARRAY(cd, NULL, iptr->op1, iptr->target);
1789                         } else {
1790                                 gen_MULTIANEWARRAY(cd, iptr->val.a, iptr->op1, NULL);
1791                         }
1792                         break;
1793
1794                 default:
1795                         *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
1796                         return false;
1797         } /* switch */
1798                 
1799         } /* for instruction */
1800
1801         gen_BBEND;
1802
1803         } /* if (bptr->flags >= BBREACHED) */
1804         } /* for basic block */
1805
1806         dseg_createlinenumbertable(cd);
1807
1808         codegen_finish(jd);
1809
1810 #ifdef VM_PROFILING
1811         vm_block_insert(jd->code->mcode + jd->code->mcodelength);
1812 #endif
1813
1814         /* branch resolving (walk through all basic blocks) */
1815
1816         for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
1817                 branchref *brefs;
1818
1819                 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
1820                         gen_resolveanybranch(((u1*) jd->code->entrypoint) + brefs->branchpos,
1821                                              ((u1 *)jd->code->entrypoint) + bptr->mpc);
1822                 }
1823         }
1824
1825         /* everything's ok */
1826
1827         return true;
1828 }
1829
1830
1831 /* createcompilerstub **********************************************************
1832
1833    Creates a stub routine which calls the compiler.
1834
1835    A stub consists of:
1836
1837    +-------------+
1838    | codeinfo *  |
1839    +-------------+ <-- stub
1840    | codeptr     |
1841    +-------------+
1842    | maxlocals   |
1843    +-------------+
1844    | TRANSLATE   |
1845    +-------------+
1846    | methodinfo  |
1847    +-------------+
1848
1849    codeptr points either to TRANSLATE or to the translated threaded code
1850
1851    all methods are called indirectly through methodptr
1852
1853 *******************************************************************************/
1854
1855 #define COMPILERSTUB_DATASIZE    1
1856 #define COMPILERSTUB_CODESIZE    4
1857
1858 #define COMPILERSTUB_SIZE        COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
1859
1860
1861 u1 *intrp_createcompilerstub(methodinfo *m)
1862 {
1863         Inst        *s;
1864         Inst        *d;
1865         codegendata *cd;
1866         codeinfo    *code;
1867         s4           dumpsize;
1868
1869         s = CNEW(Inst, COMPILERSTUB_SIZE);
1870
1871         /* set data pointer and code pointer */
1872
1873         d = s;
1874         s = s + COMPILERSTUB_DATASIZE;
1875
1876         /* Store the codeinfo pointer in the same place as in the
1877            methodheader for compiled methods. */
1878
1879         code = code_codeinfo_new(m);
1880         d[0] = (Inst *) code;
1881
1882         /* mark start of dump memory area */
1883
1884         dumpsize = dump_size();
1885         
1886         cd = DNEW(codegendata);
1887     cd->mcodeptr = (u1 *) s;
1888         cd->lastinstwithoutdispatch = ~0;
1889         cd->superstarts = NULL;
1890
1891         genarg_ainst(cd, s + 2);
1892
1893         if (m->flags & ACC_NATIVE) {
1894                 genarg_i(cd, m->parseddesc->paramslots);
1895         } else {
1896                 genarg_i(cd, m->maxlocals);
1897         }
1898
1899         gen_BBSTART;
1900         gen_TRANSLATE(cd, m);
1901         gen_BBEND;
1902         
1903 #ifdef VM_PROFILING
1904         vm_block_insert(cd->mcodeptr);
1905 #endif
1906
1907 #if defined(ENABLE_STATISTICS)
1908         if (opt_stat)
1909                 count_cstub_len += COMPILERSTUB_SIZE;
1910 #endif
1911
1912         /* release dump area */
1913
1914         dump_release(dumpsize);
1915         
1916         return (u1 *) s;
1917 }
1918
1919
1920 #if defined(WITH_FFI)
1921 static ffi_type *cacaotype2ffitype(s4 cacaotype)
1922 {
1923         switch (cacaotype) {
1924         case TYPE_INT:
1925 #if SIZEOF_VOID_P == 8
1926                 return &ffi_type_sint64;
1927 #else
1928                 return &ffi_type_sint32;
1929 #endif
1930         case TYPE_LNG:
1931                 return &ffi_type_sint64;
1932         case TYPE_FLT:
1933                 return &ffi_type_float;
1934         case TYPE_DBL:
1935                 return &ffi_type_double;
1936         case TYPE_ADR:
1937                 return &ffi_type_pointer;
1938         case TYPE_VOID:
1939                 return &ffi_type_void;
1940         default:
1941                 assert(false);
1942         }
1943 }
1944 #endif
1945
1946
1947 /* native stub:
1948 +---------+
1949 |NATIVECALL|
1950 +---------+
1951 |methodinf|
1952 +---------+
1953 |function |
1954 +---------+
1955 |cif      |
1956 +---------+
1957 */
1958
1959 #if defined(WITH_FFI)
1960 static ffi_cif *createnativecif(methodinfo *m, methoddesc *nmd)
1961 {
1962         methoddesc  *md = m->parseddesc; 
1963         ffi_cif     *pcif = NEW(ffi_cif);
1964         ffi_type   **types = MNEW(ffi_type *, nmd->paramcount);
1965         ffi_type   **ptypes = types;
1966         s4           i;
1967
1968         /* pass env pointer */
1969
1970         *ptypes++ = &ffi_type_pointer;
1971
1972         /* for static methods, pass class pointer */
1973
1974         if (m->flags & ACC_STATIC)
1975                 *ptypes++ = &ffi_type_pointer;
1976
1977         /* pass parameter to native function */
1978
1979         for (i = 0; i < md->paramcount; i++)
1980                 *ptypes++ = cacaotype2ffitype(md->paramtypes[i].type);
1981
1982         assert(ptypes - types == nmd->paramcount);
1983
1984     if (ffi_prep_cif(pcif, FFI_DEFAULT_ABI, nmd->paramcount, cacaotype2ffitype(md->returntype.type), types) != FFI_OK)
1985                 assert(0);
1986
1987         return pcif;
1988 }
1989 #endif
1990
1991
1992 u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
1993 {
1994         methodinfo   *m;
1995         codeinfo     *code;
1996         codegendata  *cd;
1997         registerdata *rd;
1998 #if defined(WITH_FFI)
1999         ffi_cif *cif;
2000 #else
2001         u1      *cif;
2002 #endif
2003
2004         /* get required compiler data */
2005
2006         m  = jd->m;
2007         cd = jd->cd;
2008         rd = jd->rd;
2009
2010         /* create method header */
2011
2012         /* Store the codeinfo pointer in the same place as in the
2013            methodheader for compiled methods. */
2014
2015         code = code_codeinfo_new(m);
2016
2017         (void) dseg_addaddress(cd, code);                      /* CodeinfoPointer */
2018         (void) dseg_adds4(cd, nmd->paramslots * SIZEOF_VOID_P); /* FrameSize      */
2019         (void) dseg_adds4(cd, 0);                               /* IsSync         */
2020         (void) dseg_adds4(cd, 0);                               /* IsLeaf         */
2021         (void) dseg_adds4(cd, 0);                               /* IntSave        */
2022         (void) dseg_adds4(cd, 0);                               /* FltSave        */
2023         dseg_addlinenumbertablesize(cd);
2024         (void) dseg_adds4(cd, 0);                               /* ExTableSize    */
2025
2026 #if defined(WITH_FFI)
2027         /* prepare ffi cif structure */
2028
2029         cif = createnativecif(m, nmd);
2030 #else
2031         cif = NULL;
2032 #endif
2033
2034         gen_BBSTART;
2035
2036         if (opt_verbosecall)
2037                 gen_TRACECALL(cd, m);
2038
2039         if (f == NULL) {
2040                 gen_PATCHER_NATIVECALL(cd, m, f, (u1 *)cif);
2041         } else {
2042                 if (opt_verbosecall)
2043                         gen_TRACENATIVECALL(cd, m, f, (u1 *)cif);
2044                 else
2045                         gen_NATIVECALL(cd, m, f, (u1 *)cif);
2046         }
2047
2048         gen_BBEND;
2049
2050         codegen_finish(jd);
2051
2052 #ifdef VM_PROFILING
2053         vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2054 #endif
2055
2056         return jd->code->entrypoint;
2057 }
2058
2059
2060 /* call jni function */
2061 Cell *nativecall(functionptr f, methodinfo *m, Cell *sp, Inst *ra, Cell *fp, u1 *addrcif)
2062 {
2063 #if defined(WITH_FFCALL)
2064         av_alist alist;
2065         methoddesc *md;
2066         Cell *p;
2067         Cell *endsp;
2068         s4 i;
2069
2070         struct {
2071                 stackframeinfo sfi;
2072                 localref_table lrt;
2073         } s;
2074
2075         md = m->parseddesc;
2076
2077         switch (md->returntype.type) {
2078         case TYPE_INT:
2079                 endsp = sp - 1 + md->paramslots;
2080                 av_start_long(alist, f, endsp);
2081                 break;
2082         case TYPE_LNG:
2083                 endsp = sp - 2 + md->paramslots;
2084                 av_start_longlong(alist, f, endsp);
2085                 break;
2086         case TYPE_FLT:
2087                 endsp = sp - 1 + md->paramslots;
2088                 av_start_float(alist, f, endsp);
2089                 break;
2090         case TYPE_DBL:
2091                 endsp = sp - 2 + md->paramslots;
2092                 av_start_double(alist, f, endsp);
2093                 break;
2094         case TYPE_ADR:
2095                 endsp = sp - 1 + md->paramslots;
2096                 av_start_ptr(alist, f, void *, endsp);
2097                 break;
2098         case TYPE_VOID:
2099                 endsp = sp + md->paramslots;
2100                 av_start_void(alist, f);
2101                 break;
2102         default:
2103                 assert(false);
2104         }
2105
2106         av_ptr(alist, _Jv_JNIEnv *, _Jv_env);
2107
2108         if (m->flags & ACC_STATIC)
2109                 av_ptr(alist, classinfo *, m->class);
2110
2111         for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2112                 switch (md->paramtypes[i].type) {
2113                 case TYPE_INT:
2114                         p -= 1;
2115                         av_long(alist, *p);
2116                         break;
2117                 case TYPE_LNG:
2118                         p -= 2;
2119                         av_longlong(alist, *(s8 *)p);
2120                         break;
2121                 case TYPE_FLT:
2122                         p -= 1;
2123                         av_float(alist, *((float *) p));
2124                         break;
2125                 case TYPE_DBL:
2126                         p -= 2;
2127                         av_double(alist, *(double *) p);
2128                         break;
2129                 case TYPE_ADR:
2130                         p -= 1;
2131                         av_ptr(alist, void *, *(void **) p);
2132                         break;
2133                 default:
2134                         assert(false);
2135                 }
2136         }
2137
2138         global_sp = sp;
2139
2140         /* create stackframe info structure */
2141
2142         codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2143                                                           (u1 *) fp, (u1 *) ra);
2144
2145         av_call(alist);
2146
2147         codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2148
2149         CLEAR_global_sp;
2150
2151         return endsp;
2152 #elif defined(WITH_FFI)
2153         methoddesc  *md = m->parseddesc; 
2154         ffi_cif     *pcif;
2155         void        *values[md->paramcount + 2];
2156         void       **pvalues = values;
2157         Cell        *p;
2158         Cell        *endsp;
2159         s4           i;
2160         _Jv_JNIEnv  *penv;
2161
2162         struct {
2163                 stackframeinfo sfi;
2164                 localref_table lrt;
2165         } s;
2166
2167         pcif = (ffi_cif *) addrcif;
2168
2169         /* pass env pointer */
2170
2171         penv = (_Jv_JNIEnv *) _Jv_env;
2172         *pvalues++ = &penv;
2173
2174         /* for static methods, pass class pointer */
2175
2176         if (m->flags & ACC_STATIC)
2177                 *pvalues++ = &m->class;
2178
2179         /* pass parameter to native function */
2180
2181         for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2182                 if (IS_2_WORD_TYPE(md->paramtypes[i].type))
2183                         p -= 2;
2184                 else
2185                         p--;
2186
2187                 *pvalues++ = p;
2188         }
2189
2190         /* calculate position of return value */
2191
2192         if (md->returntype.type == TYPE_VOID)
2193                 endsp = sp + md->paramslots;
2194         else
2195                 endsp = sp - (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1) + md->paramslots;
2196
2197         global_sp = sp;
2198
2199         /* create stackframe info structure */
2200
2201         codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2202                                                           (u1 *) fp, (u1 *) ra);
2203
2204         ffi_call(pcif, FFI_FN(f), endsp, values);
2205
2206         codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2207
2208         CLEAR_global_sp;
2209
2210         return endsp;
2211 #endif
2212 }
2213
2214
2215 u1 *createcalljavafunction(methodinfo *m)
2216 {
2217         methodinfo         *tmpm;
2218         u1                 *entrypoint;
2219         jitdata            *jd;
2220         codegendata        *cd;
2221         registerdata       *rd;
2222         s4                  dumpsize;
2223         methoddesc         *md;
2224
2225         /* mark dump memory */
2226
2227         dumpsize = dump_size();
2228
2229         /* allocate memory */
2230
2231         jd = DNEW(jitdata);
2232
2233         tmpm = DNEW(methodinfo);
2234         cd = DNEW(codegendata);
2235         rd = DNEW(registerdata);
2236
2237         jd->m = tmpm;
2238         jd->flags = 0;
2239         jd->cd = cd;
2240         jd->rd = rd;
2241
2242         /* Allocate codeinfo memory from the heap as we need to keep them. */
2243
2244         jd->code = code_codeinfo_new(tmpm); /* XXX check allocation */
2245
2246         /* setup code generation stuff */
2247
2248         MSET(tmpm, 0, u1, sizeof(methodinfo));
2249
2250         codegen_setup(jd);
2251
2252         md = m->parseddesc;
2253
2254         /* create method header */
2255
2256         (void) dseg_addaddress(cd, NULL);                      /* CodeinfoPointer */
2257         (void) dseg_adds4(cd, md->paramslots * SIZEOF_VOID_P);  /* FrameSize      */
2258         (void) dseg_adds4(cd, 0);                               /* IsSync         */
2259         (void) dseg_adds4(cd, 0);                               /* IsLeaf         */
2260         (void) dseg_adds4(cd, 0);                               /* IntSave        */
2261         (void) dseg_adds4(cd, 0);                               /* FltSave        */
2262         dseg_addlinenumbertablesize(cd);
2263         (void) dseg_adds4(cd, 0);                               /* ExTableSize    */
2264
2265
2266         /* generate code */
2267         
2268         gen_BBSTART;
2269         gen_INVOKESTATIC(cd, (Inst **)m->stubroutine, md->paramslots, 0);
2270         gen_END(cd);
2271
2272         gen_BBEND;
2273
2274         codegen_finish(jd);
2275
2276 #ifdef VM_PROFILING
2277         vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2278 #endif
2279         entrypoint = jd->code->entrypoint;
2280
2281         /* release memory */
2282
2283         dump_release(dumpsize);
2284
2285         return entrypoint;
2286 }
2287
2288
2289 /*
2290  * These are local overrides for various environment variables in Emacs.
2291  * Please do not remove this and leave it at the end of the file, where
2292  * Emacs will automagically detect them.
2293  * ---------------------------------------------------------------------
2294  * Local variables:
2295  * mode: c
2296  * indent-tabs-mode: t
2297  * c-basic-offset: 4
2298  * tab-width: 4
2299  * End:
2300  * vim:noexpandtab:sw=4:ts=4:
2301  */