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