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