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