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