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