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